Quoted from CLR via C#, it reads to me as if call
would search for the method that is defined by a base type at runtime via CLR.
Then
call
IL instruction is used to call an instance or virtual method, you must specify a variable that refers to an object. The type of the variable itself indicates which type defines the method that the CLR should call. If the variable's type doesn't define the method, base types are checked for a matching method.
and
When calling a non-virtual instance method, JIT locates the type object that corresponds to the type of the variable being used to make the call. If the type didn't defined the method being called, JIT walks down the class hierarchy toward Object looking for this method. It can do this because each type object has a field in it that refers to its base type. Then, JIT locates the entry in the type object's method table that refers to the method being called.
However, based on the following example it seems the method inheritance is checked on compile time:
class A
{
public void Foo() {}
}
class B : A {}
void Main()
{
new B().Foo();
}
IL_0000: newobj UserQuery+B..ctor
IL_0005: call UserQuery+A.Foo // Not B.Foo, resolved by C# complier.
Am I correct?
Even if I do this:
void Main()
{
B x = new B();
x.Foo();
}
IL_0000: newobj UserQuery+B..ctor
IL_0005: stloc.0 // x
IL_0006: ldloc.0 // x
IL_0007: callvirt UserQuery+A.Foo // Not B.Foo, resolved by C# complier.
Update:
Now I understand that the resolution is static.
And I believe that the variable type that the JIT needs is actually the class specified by the metadata token.
Duplicate Alert
Actually it is a duplicate to Is Richter mistaken when describing the internals of a non-virtual method call?
Glad that there is another person who had the same question as me.