相关疑难解决方法(0)

C#中的拳击事件

我正在尝试收集C#中发生装箱的所有情况:

c# boxing value-type

82
推荐指数
2
解决办法
4007
查看次数

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

这更像是一个'奇怪的原因',而不是一个特定的问题,但请看下面的代码

        static void Main(string[] args)
        {
            int val = 10;

            Console.WriteLine("val is {0}", val); // (1)
            Console.WriteLine("val is {0}", val.ToString()); //(2)


        }
Run Code Online (Sandbox Code Playgroud)

在情况(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)
Run Code Online (Sandbox Code Playgroud)

在我明确调用toString方法的情况下(2)我得到了

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)
Run Code Online (Sandbox Code Playgroud)

所以在case(1)中,即使int重写toString,也会将值类型装箱并调用toString方法,这可能会调用vtable覆盖

所以结果完全相同,但显式的toString避免了装箱操作

谁知道为什么?

=编辑=
确定要清楚,令我感到困惑的是,我开始假设即使int派生自System.ValueType,而System.ValueType又派生自System.Object,因为它包含toString,GetHashCode等.
所以在我的天真view(可能来自C++),如果我重写从System.Object派生的方法,那么就不需要强制转换为System.Object(因此将值类型框),因为存在overriden方法,编译器将自动引用vtable条目对于类型.
我也假设调用Console.WriteLine()隐式调用int.toString所以也许这就是我出错的地方.希望有道理

好的 - 全部排序.谢谢大家直截了当.所有这些都与我的糟糕假设有关,即Console.WriteLine正在进行隐式字符串转换.不要问我为什么这么想 - 看起来很明显现在错误:)

c# performance

13
推荐指数
2
解决办法
2570
查看次数

标签 统计

c# ×2

boxing ×1

performance ×1

value-type ×1