Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
280 views
in Technique[技术] by (71.8m points)

c# - Why does implicitly calling toString on a value type cause a box instruction

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)


        }

In case (1) the following IL is output

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)

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)

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

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

Anyone know why?

=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

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 :)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

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);

As the int is a value type, boxing occurs.

The second case is equivalent to:

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...