5

可以说,我在 c# 中有以下代码

int x = 0;
x.ToString();

这是否在内部进行了 x 的装箱?有没有办法从视觉工作室看到这种情况?

4

2 回答 2

7

在这种特定情况下,您使用的是System.Int32(an int)。该类型重新定义ToString,EqualsGetHashCode,因此没有装箱。

如果您使用 astruct不会重新定义ToString您将拥有的是 a constrained callvirtto 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()
于 2013-09-04T13:52:04.400 回答
6

这是您的代码生成的 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 方法指令。

如果您想在调用时避免装箱EqualsGetHashCode并且ToString在值类型上,您需要覆盖这些方法。

于 2013-09-04T13:51:29.253 回答