可以说,我在 c# 中有以下代码
int x = 0;
x.ToString();
这是否在内部进行了 x 的装箱?有没有办法从视觉工作室看到这种情况?
可以说,我在 c# 中有以下代码
int x = 0;
x.ToString();
这是否在内部进行了 x 的装箱?有没有办法从视觉工作室看到这种情况?
在这种特定情况下,您使用的是System.Int32
(an int
)。该类型重新定义ToString
,Equals
和GetHashCode
,因此没有装箱。
如果您使用 astruct
不会重新定义ToString
您将拥有的是 a constrained callvirt
to System.Object.ToString()
。约束的定义:
当 callvirt 方法指令以 constraint thisType 为前缀时,指令执行如下:
- 如果 thisType 是值类型并且 thisType 实现了方法,则 ptr 未经修改地作为“this”指针传递给调用方法指令,用于通过 thisType 实现方法。
- 如果 thisType 是值类型并且 thisType 没有实现方法,则 ptr 被取消引用、装箱并作为“this”指针传递给 callvirt 方法指令。
所以如果值类型实现就没有ToString
装箱,如果没有实现它就没有装箱......有趣。我不知道。
GetType()
对于像在值类型中定义的非虚拟方法,System.Object
总是装箱。刚刚测试过:
5.GetType();
生成的 IL 代码:
IL_0001: ldc.i4.5
IL_0002: box [mscorlib]System.Int32
IL_0007: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
这是您的代码生成的 IL:
IL_0001:ldc.i4.0 IL_0002: stloc.0 // x IL_0003: ldloca.s 00 // x IL_0005:调用 System.Int32.ToString
如您所见,没有进行拳击。
另一方面,这段代码
object x = 0;
x.ToString();
不会令人惊讶地引起拳击:
IL_0001:ldc.i4.0 IL_0002:框 System.Int32 IL_0007: stloc.0 // x IL_0008: ldloc.0 // x IL_0009: callvirt System.Object.ToString
通常,如果 的类型x
不是int
任何值类型 ( struct
),那么您必须覆盖ToString
以避免装箱。具体来说,发出一个受约束 callvirt
的:
如果 thisType 是值类型并且 thisType 实现了方法,则 ptr 未经修改地作为“this”指针传递给调用方法指令,用于通过 thisType 实现方法。
如果 thisType 是一个值类型并且 thisType 没有实现方法,则 ptr 被取消引用,装箱,并作为“this”指针传递给 callvirt 方法指令。
如果您想在调用时避免装箱Equals
,GetHashCode
并且ToString
在值类型上,您需要覆盖这些方法。