Non-virtual calls to virtual methods
C# compiler is known to emit virtual calls for non-virtual methods (callvirt instead of call IL instruction, maybe that be the topic of my next post). However, sometimes it's forced to do the exact opposite
Consider the following code
class B
{
public virtual void Foo()
{
Console.WriteLine("Base::Foo");
}
}
class D : B
{
public override void Foo()
{
base.Foo();
this.Foo(); // this is infinite recursion. Put just for example
Console.WriteLine("Derived::Foo");
}
}
Here B::Foo is a virtual method and hence should be called virtually for both the calls in D::Foo. However, that's not the case.
For the above code the emitted IL looks like
L_0001: ldarg.0
L_0002: call instance void BaseCall.B::Foo()
L_0007: nop
L_0008: ldarg.0
L_0009: callvirt instance void BaseCall.B::Foo()
So for base.Foo() call the non-virtual call instruction is generated and for the this.Foo() call the virtual callvirt instruction is generated.
The reason is obviously simple. If a virtual call was made on base.Foo() then the call would've landed in the derived D::Foo which would again call base.Foo() resulting in infinite recursion.
Any guess on what happens for the following code
class B
{
public virtual void Foo()
{
Console.WriteLine("Base::Foo");
}
}
class C : B
{
public override void Foo()
{
Console.WriteLine("C::Foo");
}
}
class D : C
{
public override void Foo()
{
base.Foo();
Console.WriteLine("Derived::Foo");
}
}
Comments
Anonymous
September 26, 2007
PingBack from http://www.artofbam.com/wordpress/?p=3300Anonymous
September 30, 2007
The comment has been removedAnonymous
July 02, 2008
Sometime back I had posted about a case where non-virtual calls are used for virtual methods and promised