为什么在值类型上隐式调用toString会引起Box指令 [英] Why does implicitly calling toString on a value type cause a box instruction

查看:47
本文介绍了为什么在值类型上隐式调用toString会引起Box指令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这比特定问题更能说明问题,但请看下面的代码

This is more a 'wonder why' than a specific issue but look at the following code

        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)

以防万一(2 ),在我明确调用toString方法的地方

In case (2) where I explicitly call the toString method I get

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覆盖了toStrin g,将值类型装箱,然后调用toString方法,然后大概调用vtable覆盖

So in case (1), even though int overrides toString, the value type is boxed and the toString method is called which presumably then calls the vtable override

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

So the result is exactly the same but an explicit toString avoids a boxing operation

有人知道为什么吗?

= Edit =

好​​吧,这是什么令我感到困惑的是,我开始的假设是,即使int派生自System.ValueType,又反过来派生自System.Object,因为它包含toString,GetHashCode等。

可能来自C ++),如果我重写了从System.Object派生的方法,则无需强制转换为System.Object(因此将值类型框),因为存在重写的方法,并且编译器将自动引用vtable条目

我还假设调用Console.WriteLine()隐式会调用int.toString,所以也许这就是我要出错的地方。希望有道理

=Edit=
OK to be clear, what's confusing me is that I'm starting with the assumption that even though int derives from System.ValueType, that in turn derives from System.Object because it contains toString, GetHashCode etc.
So in my naive view ( probably from C++), if I override a method derived from System.Object then there is no need to cast to System.Object ( and hence box the value type ) because an overriden method exists and the compiler will automatically reference the vtable entry for the type.
I'm also assuming that calling Console.WriteLine() implicitly calls int.toString so perhaps that's where I'm going wrong. Hope that makes sense

确定-全部排序。谢谢大家的帮助。这与我的一个错误假设有关,即Console.WriteLine正在执行隐式字符串转换。不要问我为什么会这样-似乎令人眼花obvious乱,现在看来是多么错误:)

OK - all sorted. Thanks all for setting me straight. All to do with a bad assumption of mine that Console.WriteLine was doing an implicit string conversion. Don't ask me why I thought that - seems blindingly obvious how wrong that is now :)

推荐答案

您不是在隐式调用 ToString WriteLine 方法没有重载,该方法在格式字符串之后接收字符串,只接收对象。

You are not implicitly calling ToString at all. The is no overload of the WriteLine method that takes strings after the format string, it only takes objects.

因此,则不是隐式调用 ToString ,而是将 int 隐式转换为 object 。第一种情况等效于:

So, you are not implicitly calling ToString, you are implicitly converting the int to object. The first case is equivalent to:

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

由于 int 是一种值类型,

第二种情况等效于:

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

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

As the string is a reference type, casting it to object doesn't actually cause any code to be emitted. It just matches the type with the method signature.

这篇关于为什么在值类型上隐式调用toString会引起Box指令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆