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 :)
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With