星期四, 九月 27, 2007

Non-virtual calls to virtual methods



 
 

Sent to you by Hudong via Google Reader:

 
 

via MSDN Blogs by abhinaba on 9/27/07

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

 
 

Things you can do from here:

 
 

没有评论:

发表评论