代码之家  ›  专栏  ›  技术社区  ›  zebrabox

为什么对值类型隐式调用toString会导致box指令

  •  13
  • zebrabox  · 技术社区  · 17 年前

    这与其说是一个具体问题,不如说是一个“奇怪的原因”,但请看下面的代码

            static void Main(string[] args)
            {
                int val = 10;
    
                Console.WriteLine("val is {0}", val); // (1)
                Console.WriteLine("val is {0}", val.ToString()); //(2)
    
    
            }
    

    在情况(1)中,输出以下IL

    IL_0000:  nop
      IL_0001:  ldc.i4.s   10
      IL_0003:  stloc.0
      IL_0004:  ldstr      "val is {0}"
      IL_0009:  ldloc.0
      IL_000a:  box        [mscorlib]System.Int32
      IL_000f:  call       void [mscorlib]System.Console::WriteLine(string,
                                                                    object)
    

    IL_0014:  nop
      IL_0015:  ldstr      "val is {0}"
      IL_001a:  ldloca.s   val
      IL_001c:  call       instance string [mscorlib]System.Int32::ToString()
      IL_0021:  call       void [mscorlib]System.Console::WriteLine(string,
                                                                    object)
    

    因此,在案例(1)中,即使int重写toString,值类型也会被装箱并调用toString方法,该方法可能会调用vtable重写

    因此,结果完全相同,但显式toString避免了装箱操作

    有人知道为什么吗?




    我还假设调用Console.WriteLine()时 含蓄地 调用int.toString,所以可能这就是我出错的地方。希望这是有道理的

    好的-全部排序。谢谢大家帮我澄清。这一切都与我的错误假设有关,即Console.WriteLine正在执行隐式字符串转换。不要问我为什么会这样想——现在看来这是多么明显的错误:)

    3 回复  |  直到 17 年前
        1
  •  14
  •   Guffa    17 年前

    你不是在暗中打电话 ToString WriteLine

    所以,你不是在暗中打电话 托斯特林 int 到 object . 第一种情况相当于:

    Console.WriteLine("val is {0}", (object)val);
    

    作为 是值类型,则会发生装箱。

    第二种情况相当于:

    Console.WriteLine("val is {0}", (object)val.ToString());
    

    由于字符串是引用类型,将其强制转换为对象实际上不会导致发出任何代码。它只是将类型与方法签名相匹配。

        2
  •  5
  •   Adam Robinson    17 年前

    因为首先你要通过考试 int 作为 object 打电话给 Console.WriteLine() int ToString 直接,避免拳击和传球 string WriteLine ,它已经是引用类型。

        3
  •  2
  •   JaredPar    17 年前