In combination with IL and Windbg, we can see that. Net calls inherit the execution sequence of virtual methods. ilwindbg
First test the Code:
Using System; using System. collections. generic; using System. linq; using System. text; using System. threading. tasks; namespace TestVirt {class Program {static void Main (string [] args) {A c1 = new C (); c1.Foo (); C c2 = new C (); c2.Foo (); Console. readLine () ;}} class A {public virtual void Foo () {Console. writeLine ("Call on. foo () ") ;}} class B: A {public override void Foo () {Console. writeLine ("Call on B. foo () ") ;}} class C: B {public new void Foo () {Console. writeLine ("Call on C. foo ()");}}}View Code
Maybe you have no doubt about the result of C c2 = new C (); but you are puzzled by the result of A c1 = new C. Let's take a look at the difference. Let's first look at what the final IL code looks like:
. Method private hidebysig static void Main (string [] args) cel managed {. entrypoint // code size 34 (0x22 ). maxstack 1. locals init ([0] class TestVirt. A c1, [1] class TestVirt. C c2) IL_0000: nop IL_0001: newobj instance void TestVirt. C ::. ctor () IL_0006: stloc.0 IL_0007: ldloc.0 IL_0008:Callvirt instance void TestVirt. A: Foo ()IL_000d: nop IL_000e: newobj instance void TestVirt. C:. ctor () IL_0013: stloc.1 IL_0014: ldloc.1 IL_0015:Callvirt instance void TestVirt. C: Foo ()IL_001a: nop IL_001b: call string [mscorlib] System. Console: ReadLine () IL_0020: pop IL_0021: ret} // end of method Program: Main
According to the results of IL, we can see that the difference between the two calls is that one is the Foo of Call A and the other is the Foo of C.
However, you have noticed that new objects share the same memory layout.
Use WinDbg to see what the MethodTable of the new object looks like:
No. The method table of this C object also contains the Foo method defined by C and the Foo method of the parent object of the previous level.
Combined with the results of IL and the Dump results of the method table of the C object, I believe the reader has understood why the two calls are different.
Forget it, let's briefly describe it. First, the two methods of calling the request are obviously different based on the il results. Second, you can see that the method table referenced by our C object does have two Foo methods.
Well, can the requests of the same type of objects for different method calls be separated? Of course!
PS: Someone may ask: why is there no MethodTable in your requested A. Foo?
Make up your mind. Brother: B gave it to override.