C# 取消装箱不会创建值的副本。是这样吗?
我正在读微软的教室培训材料。我读了以下内容 拆箱 拆箱是拳击的反面。它是将引用类型显式转换为 值类型。取消装箱检索对对象中包含的值类型的引用。 取消装箱操作涉及检查对象实例以确保对象 实例是给定值类型的装箱值。然后,实例中的值为 复制到值类型变量中 ** 取消装箱返回一个指向装箱对象内数据的指针,并且不创建数据的副本。 ** 我不太明白我强调的那句话。它表示,当取消装箱对象时,它不会创建副本,只返回一个指针。如果这是真的,那么将在堆中分配一个值类型变量,对吗C# 取消装箱不会创建值的副本。是这样吗?,c#,.net,C#,.net,我正在读微软的教室培训材料。我读了以下内容 拆箱 拆箱是拳击的反面。它是将引用类型显式转换为 值类型。取消装箱检索对对象中包含的值类型的引用。 取消装箱操作涉及检查对象实例以确保对象 实例是给定值类型的装箱值。然后,实例中的值为 复制到值类型变量中 ** 取消装箱返回一个指向装箱对象内数据的指针,并且不创建数据的副本。 ** 我不太明白我强调的那句话。它表示,当取消装箱对象时,它不会创建副本,只返回一个指针。如果这是真的,那么将在堆中分配一个值类型变量,对吗 嗯,这是真的,但不是全部 取消装箱本
嗯,这是真的,但不是全部 取消装箱本身只返回一个指向数据的指针,但不能使用该指针访问C#中的数据。在C#中取消绑定值时,总是将其复制到某个位置 例如:
object o = 42; //box
int i = (int)o; //unbox
拆箱iself获取指向对象
o
中的值42
的指针,然后将该值复制到变量i
,除了Guffa所说的,这里还有一些附加信息:
- 您引用的文本中描述的“取消装箱”操作描述了
CIL指令。CIL标准对unbox
有如下说明: 不同于unbox
,它是 在中使用的值类型的副本 对象,框
不需要复制 对象中的值类型。 通常,它只计算 指定的值类型的地址 盒子里已经有了 反对unbox
- 在C#中使用的取消装箱转换不会编译为
它们会编译为另一条名为unbox
: […]unbox的指令。任何
指令都提取其中包含的值 obj(类型为unbox。任何
)。(它相当于O
后跟unbox
) 在英语中,这意味着ldobj
都会执行一个unbox操作(unbox。任何
)-将指针推送到计算堆栈上,然后执行复制操作(unbox
),将指针转换为值类型中包含的实际值,并将其推送到计算堆栈上 为完整起见,以下是对ldobj的描述:ldobj
指令复制一个值 到求值堆栈。[…]src是非托管指针 (本机int)或托管指针 (&). [……] [理由:联合国ldobj
指令可用于传递 作为参数的值类型。结束 [理由]ldobj
据我所知,C#编译器从不使用
unbox
或ldobj
,它总是使用unbox.any
进行unboxing,并使用ldind.
取消引用(例如ref
/out
参数).是否有指向未绑定值的指针可以直接使用而无需复制值的地方?@RAM:我不这么认为,至少不容易。也许您可以使用fixed
将对象固定在内存中,并获取指向该值的指针,但这比仅复制该值要复杂得多。被装箱的值很小,因此没有真正的理由避免复制它。@colinfang:取消装箱值会得到一个指向对象中的值的指针,它不会复制该值,直到您实际将其用于某个目的。取消绑定结构并在其中使用字段将从已装箱的结构中复制该字段的值。解释非常清楚。从你和Guffa给出的答案中,我清楚地理解了拆箱。谢谢你的解释和时间记忆