C#身份转换的值表示保留含义及装箱对值类型表示的疑问
C#身份转换中“值的表示”详解及引用类型与装箱的差异
什么是“值的表示”?
这里的**“表示(representation)”是CLR层面的正式概念,指的是数据在内存中的二进制存储结构、存储位置以及底层访问逻辑**。它决定了CLR如何识别、存储和操作一段数据。
引用类型转object:不改变值的表示
引用类型(如string、自定义类、委托等)在CLR中的内存表示本质是指向托管堆中对象实例的指针(32位系统是4字节,64位是8字节)。当你将引用类型转换为object时:
- 仅改变了编译时的类型标识,让编译器将该引用视为
object类型,但内存中存储的指针值完全不变。 - 以你的示例为例:
这段代码的委托赋值利用了引用类型的协变特性:public delegate void PrintString(string value); public static void PrintAnything(object value) { Console.WriteLine(value); } PrintString ps = PrintAnything;string是object的子类,将接受object的方法赋值给接受string的委托时,底层传递的引用没有任何变化——PrintAnything处理的string参数,依然是指向托管堆中string对象的原指针,只是编译时被标记为object类型。 - 总结:引用类型转
object没有修改内存中的二进制数据(指针值),只是调整了类型的“认知标签”,因此是“保留值表示”的身份转换。
值类型装箱:改变值的表示
值类型(如int、struct)默认的内存表示是值本身的二进制数据(比如int就是4字节的数值),通常存储在栈上(或作为引用类型字段存在堆上),没有额外的对象元数据。当值类型装箱时:
- CLR会在托管堆上创建一个新的对象实例,该实例包含CLR所需的对象头(类型标识、同步块索引等元数据)。
- 将栈上的值类型数据完整复制到堆对象的实例数据区域。
- 返回指向这个堆对象的引用。
- 此时,原来的值类型(栈上的纯数值)和装箱后的对象(堆上带元数据的结构),内存表示完全不同:前者是直接存储值,后者是包含元数据的对象结构,因此装箱操作改变了值的表示。
内容的提问来源于stack exchange,提问作者cookieMonster
相关产品推荐
相关产品推荐

