valueType.ToString()是否对valueType进行了强制转换?

时间:2013-09-04 13:46:59

标签: c# value-type boxing unboxing

我想说,我在c#

中有以下代码
int x = 0;
x.ToString();

这内部是否有x的拳击? 有没有办法从视觉工作室看到这种情况?

2 个答案:

答案 0 :(得分:6)

以下是您的代码生成的IL:

IL_0001:  ldc.i4.0    
IL_0002:  stloc.0     // x
IL_0003:  ldloca.s    00 // x
IL_0005:  call        System.Int32.ToString

你可以看到没有发生拳击。

另一方面,这段代码

object x = 0;
x.ToString();

不会令人惊讶地导致拳击:

IL_0001:  ldc.i4.0    
IL_0002:  box         System.Int32
IL_0007:  stloc.0     // x
IL_0008:  ldloc.0     // x
IL_0009:  callvirt    System.Object.ToString

通常,如果x的类型不是int而是任何值类型(struct),那么您必须覆盖ToString以避免装箱。具体而言,constrained callvirt会被发出:

  
      
  • 如果thisType是一个值类型而thisType实现了方法,那么ptr将被未经修改地传递为调用方法指令的'this'指针,用于通过thisType实现方法。

  •   
  • 如果thisType是一个值类型而thisType没有实现方法,则ptr被解除引用,装箱,并作为'this'指针传递给callvirt方法指令。

  •   

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

答案 1 :(得分:6)

在这种特定情况下,您使用的是System.Int32int)。该类型重新定义了ToStringEqualsGetHashCode,因此没有装箱。

如果您使用的struct未重新定义ToString,则constrained callvirtSystem.Object.ToString()的内容为ToStringconstrained的定义:

  

当callvirt方法指令以约束thisType作为前缀时,指令执行如下:

     
      
  • 如果thisType是一个值类型而thisType实现了方法,那么ptr将被未经修改地传递为调用方法指令的'this'指针,用于通过thisType实现方法。
  •   
  • 如果thisType是值类型而thisType没有实现方法,那么ptr将被取消引用,盒装,并作为'this'指针传递给callvirt方法指令。
  •   

因此,如果值类型实现GetType()并且如果它没有实现它就有拳击没有装箱......有趣。我不知道。

对于System.Object中定义的5.GetType(); 等非虚拟方法,值类型始终为框。刚刚测试过:

IL_0001: ldc.i4.5
IL_0002: box [mscorlib]System.Int32
IL_0007: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()

产生的IL代码:

{{1}}