取消装箱不会创建值的副本.这是正确的吗?

RAM*_*RAM 10 .net c#

我正在阅读微软的Class Room Training Materil.我读了以下内容

拆箱拆箱与拳击相反.它是将引用类型显式转换为值类型.取消装箱将检索对对象中包含的值类型的引用.取消装箱操作涉及检查对象实例以确保对象实例是给定值类型的装箱值.然后,将实例中的值复制到值类型变量中.

**

取消装箱会返回指向装箱对象内数据的指针,而不会创建数据副本.

**

我真的不明白我强调的那条线.它表示当拆箱装箱对象时,它不会创建副本,它只返回一个指针.如果这是真的,那么值类型变量将在Heap中分配吗?

内存

Tim*_*mwi 17

除了Guffa所说的,还有一些额外的信息:

  • 您引用的文本描述的"拆箱"操作描述了unboxCIL指令.CIL标准有这样的说法unbox:

    不像box,这需要使值类型在对象使用的一个副本,unbox要求的值类型从对象复制.通常,它只是计算已装箱对象内部已存在的值类型的地址

  • 您在C#中使用的取消装箱转换编译到unbox.它们被编译成另一个指令unbox.any:

    [...] unbox.any指令提取obj(类型O)中包含的值 .(相当于unbox后面跟着ldobj.)

    在英语中,这意味着unbox.any执行拆箱操作(unbox) - 将指针推送到评估堆栈 - 然后执行复制操作(ldobj),该操作将指针转换为值类型中包含的实际值,并将其推送到评估堆栈上.

    为了完整起见,以下是对以下内容的描述ldobj:

    ldobj指令将值复制到评估堆栈.[...] src是一个非托管指针(native int)或托管指针(&).[...]

    [原理:该 ldobj指令可用于传递值类型作为参数.最终理由 ]

据我所知,C#编译器从不使用unbox或者ldobj,它总是用于unbox.any取消装箱,以及ldind.*取消引用引用(例如ref/ out参数).

  • 非常明确的解释.根据你和Guffa给出的答案,我清楚地了解拆箱.谢谢你的精彩解释和时间 - 拉姆 (2认同)

Guf*_*ffa 11

嗯,这是真的,但不是全局.

拆箱本身只返回指向数据的指针,但您不能使用它来访问C#中的数据.如果在C#中取消装箱值,则始终将其复制到某处.

例:

object o = 42; //box
int i = (int)o; //unbox
Run Code Online (Sandbox Code Playgroud)

unboxing iself获取指向42对象中值的指针o,然后将值复制到变量中i.