如何解决非虚拟实例方法继承? [英] How is non-virtual instance method inheritance resolved?

查看:166
本文介绍了如何解决非虚拟实例方法继承?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

通过C#从CLR引用,它读取到我,好像调用会在运行时通过CLR搜索由基类型定义的方法。

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.


然后调用 IL指令用于调用实例或虚拟
方法必须指定引用对象的变量。变量本身的类型
表示哪个类型定义了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.

p>

and


当调用非虚拟实例方法时,JIT定位与正在使用的变量类型相对应的类型
对象
调用。如果类型没有定义被调用的方法,JIT
沿类层次结构向下寻找这个方法的对象。
它可以这样做,因为每个类型对象在其中有一个字段引用
到它的基类型。然后,JIT在类型对象的
方法表中找到引用正在调用的方法的条目。

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.

我是否正确?

我这样做:

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.

我相信JIT需要的变量类型实际上是元数据令牌指定的类。

And I believe that the variable type that the JIT needs is actually the class specified by the metadata token.

实际上它是重复的

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.

推荐答案

引用说的是变量的类型,而不是变量引用的对象实例的类型。变量类型是静态已知的,所有的决策都是静态的。

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.

C#编译器解析精确的方法来调用并编码到IL。如果引用的程序集不更改,则JIT不必自己执行任何方法解析。

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. JIT无法查看任何对象引用,因为它需要静态决定。它查看堆栈上的元素所具有的类型,无论元素来自哪里。在可验证的代码中,这是明确的。

  2. 是的,方法由程序集+类型+方法名和签名引用。返回类型。非常精确。

这篇关于如何解决非虚拟实例方法继承?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆