Sent to you by Hudong via Google Reader:
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:
- on MSDN Blogs
- Subscribe to MSDN Blogs using Google Reader
- Get started using Google Reader to easily keep up with all your favorite sites
没有评论:
发表评论