引用类型变量分配的指针/引用的隐藏值及相关技术疑问
关于C#引用类型变量底层值的详解
嘿,这个问题问到了C#类型系统的底层细节,咱们一步步把它说清楚:
1. 引用类型变量存储的实际值是什么?
引用类型变量(比如你的harrysQuestion)存储的是堆上对象的内存地址,本质上是一个数值:
- 在32位操作系统/进程中,这个值是一个32位整数(4字节);
- 在64位系统/进程中,是一个64位整数(8字节)。
你没法直接把它写成普通的int或string——C#为了类型安全和抽象性,把这个底层数值给封装起来了,日常代码里你看不到它的具体值,也不能直接把一个整数赋值给引用变量。如果非要举个例子,它的样子类似十六进制的内存地址,比如0x000001F8A3B2C4D6(这只是模拟的示例,实际地址由CLR的内存分配器决定)。
2. 能不能用这个底层值给变量分配引用?
正常的安全代码里不行,因为C#不允许直接操作裸内存地址。但如果使用unsafe代码块(需要在项目设置里启用“允许不安全代码”),你可以绕过这个限制,比如:
using System.Runtime.CompilerServices; unsafe class Program { static void Main() { Question harrysQuestion = new Question(); // 获取引用对应的内存地址,转换为ulong类型存储 void* objectPtr = Unsafe.AsPointer(ref harrysQuestion); ulong address = (ulong)objectPtr; // 把存储的地址再转回引用类型变量 Question harrysQuestionAgain; Unsafe.AsRef(ref harrysQuestionAgain) = Unsafe.AsRef<Question>((void*)address); // 此时两个变量指向同一个对象 System.Console.WriteLine(harrysQuestion == harrysQuestionAgain); // 输出True } } class Question { }
⚠️ 注意:这种做法极度不安全!如果原对象被垃圾回收(GC)回收了,这个地址就变成了无效的“野指针”,会导致程序崩溃、内存错误等问题,日常开发绝对不建议使用。
3. 赋值引用变量时,底层发生了什么?
当你执行Question harrysQuestionAgain = harrysQuestion;时:
harrysQuestionAgain会拿到和harrysQuestion完全相同的内存地址值;- 这个地址确实是一个指向计算机内存某位置的数字;
- 底层来看,这个地址就是一个值类型(32位
int或64位long),但C#把它包装成了“引用”的抽象概念,不让你直接当成普通值类型操作,以此保证内存安全。
简单说,这两个变量现在都指向堆上同一个Question对象,修改其中一个变量的成员,另一个也会看到变化。
内容的提问来源于stack exchange,提问作者Harry
相关产品推荐
相关产品推荐

