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