Boxing Mystery in Overloaded and Overridden Method
Recently I have produced a code with strange behaviour in my real C# project. Look at this code:
class BaseMystery
{
public virtual void Foo(int i) { }
}
class Mystery : BaseMystery
{
private void Foo(object i)
{
Console.WriteLine("Finished.");
}
public new void Foo(int i)
{
Foo(i);
}
}
static void Main(string[] args)
{
Mystery mystery = new Mystery();
mystery.Foo(3);
}
It produces:
Process is terminated due to StackOverflowException.
There is nothing strange. The method
Mystery.Foo(int) is called repeatedly. Then I replaced hidding method Mystery.Foo(int) by overriding method:class BaseMystery
{
public virtual void Foo(int i) { }
}
class Mystery : BaseMystery
{
private void Foo(object i)
{
Console.WriteLine("Finished.");
}
public override void Foo(int i)
{
Foo(i);
}
}
static void Main(string[] args)
{
Mystery mystery = new Mystery();
mystery.Foo(3);
}
And the output is:
Finished.
Hah! What is the matter? Let us go to explore IL code of method
Mystery.Foo(int):public new void Foo(int)
.method public hidebysig instance void Foo(int32 i) cil managed
{
.maxstack 8
L_0000: nop
L_0001: ldarg.0
L_0002: ldarg.1
L_0003: call instance void BoxingMystery.Program/Mystery::Foo(int32)
L_0008: nop
L_0009: ret
}
and
public override void Foo(int)
.method public hidebysig virtual instance void Foo(int32 i) cil managed
{
.maxstack 8
L_0000: nop
L_0001: ldarg.0
L_0002: ldarg.1
L_0003: box int32
L_0008: call instance void BoxingMystery.Program/Mystery::Foo(object)
L_000d: nop
L_000e: ret
}
Argument
i has been boxed. Why? I would expect that the IL body of method Mystery.Foo(int) will be the same in new and override declaration but it is different. It is very strange behaviour of compiler. What is your explanation? Overridded method in my real project was the right one. In addition, I renamed the methods, because my colleagues could be confused like me.