Test the code First:
usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespacetestvirt{classProgram {Static voidMain (string[] args) {A C1=NewC (); C1. Foo (); C C2=NewC (); C2. Foo (); Console.ReadLine (); } } classA { Public Virtual voidFoo () {Console.WriteLine ("Call on A.foo ()"); } } classb:a { Public Override voidFoo () {Console.WriteLine ("Call on B.foo ()"); } } classc:b { Public New voidFoo () {Console.WriteLine ("Call on C.foo ()"); } }}
View Code
You may have no doubt about the result of c C2 = new C (), but the result of a C1 = new C () is Baisibuxie. Oh, we take a slow look at this difference, first to see what the final IL code looks like:
. method private Hidebysig static void Main (string[] args) CIL managed{ . entrypoint //code size (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
As a result of IL, we can clearly see that the two invocations are different in that one is called A's Foo, and the other is the C foo.
But here you notice: Our new is the same object, they have the same memory layout.
Use WinDbg to see what the methodtable of our new object looks like:
See, the method table for this C object includes the Foo method of the C-defined Foo and the previous level parent object.
Combining the results of IL and the dump results of the C object's method table, I believe crossing has understood why the two calls are different.
OK, or simply describe it: first of all, according to the result of IL obviously two times the method of invoking the request is different; second, you can see that our C object refers to a method table that does have two Foo methods.
Oh, so the same type of object to different methods call request is it possible to separate it? Of course it is!
PS: Someone might ask: why did I ask for A.foo () You don't have this methodtable?
The brain to fill the bar elder brother: by B to override.
Combine IL and WinDbg to see. NET calls inherit virtual methods execution order