Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How is non-virtual instance method inheritance resolved?

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.

like image 883
colinfang Avatar asked Jun 25 '26 23:06

colinfang


1 Answers

The quote speaks of the type of the variable, not of the type of the object instance the variable refers to. The variable type is statically known so all decisions are static.

The C# compiler resolves the exact method to call and encodes it into the IL. If the referenced assemblies do not change, the JIT does not have to do any method resolution by itself. The C# compiler does that because it wants to apply C# semantics, not CLR semantics.

To answer your edited-in questions:

  1. The JIT cannot look at any object reference because it needs to decide statically. It looks at the type that the element on the stack has, wherever that element came from. In verifiable code this is unambiguous. The variable type does not influence method binding though (IOW your question 1 is irrelevant).
  2. Yes, a method is referenced by assembly+type+method name and signature incl. return type. Very precise.
like image 104
usr Avatar answered Jun 28 '26 13:06

usr



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!