You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

引用类型变量分配的指针/引用的隐藏值及相关技术疑问

关于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:09:13