I would write this question directly to Jeffrey Richter, but last time he didn\'t answer me :) so I will try to get an answer with your help here, guys :)
In the book \"
As answered by @usr in the similar question I posted How is non-virtual instance method inheritance resolved?:
Runtime usually means "when/everytime the code runs". The JIT resolution here is only involved once before the code runs. What the JIT does is not being referred to by saying "at runtime".
Also in Jeffrey's words
JIT compiler locates the type object that corresponds to the type of the variable being used to make the call.
The variable type here I believe means "the class specified by the metadata token" (ECMA 335 III.3.19 call) based on which JIT resolves the method destination.
C# compiler always figures out the correct method to call, and put that info into the metadata token. So JIT never has to "walk down the class hierarchy". (But it can if you manually change the metadata token to an inherited method)
class A
{
public static void Foo() {Console.WriteLine(1); }
public void Bar() { Console.WriteLine(2); }
}
class B : A {}
class C : B {}
static void Main()
{
C.Foo();
new C().Bar();
C x = new C();
x.Bar();
Console.ReadKey();
}
IL_0000: call void ConsoleApplication5.Program/A::Foo() // change to B::Foo()
IL_0005: newobj instance void ConsoleApplication5.Program/C::.ctor()
IL_000a: call instance void ConsoleApplication5.Program/A::Bar() // change to B::Bar()
IL_000f: newobj instance void ConsoleApplication5.Program/C::.ctor()
IL_0014: stloc.0
IL_0015: ldloc.0
IL_0016: callvirt instance void ConsoleApplication5.Program/A::Bar() // change to B::Bar()
IL_001b: call valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()
IL_0020: pop
IL_0021: ret
If we use Ildasm + Ilasm to change A::Foo()
to B::Foo()
, and to change A::Bar()
to B.Bar()
, the application runs fine.