通过 C# 从 CLR 引用,它读起来就像call
将在运行时通过 CLR 搜索由基类型定义的方法。
Then call
IL指令用于调用实例或虚拟
方法中,您必须指定一个引用对象的变量。方式
变量本身的类型指示定义该方法的类型
CLR 应该调用。如果变量的类型没有定义方法,
检查基本类型是否有匹配的方法。
and
当调用非虚实例方法时,JIT会定位类型
与用于创建的变量的类型相对应的对象
的电话。如果类型没有定义被调用的方法,JIT
沿着类层次结构向 Object 走去寻找此方法。
它可以做到这一点,因为每个类型对象都有一个引用的字段
为其基本类型。然后,JIT 在类型对象的条目中定位该条目
引用被调用方法的方法表。
但是,根据以下示例,似乎在编译时检查方法继承:
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:
现在我明白分辨率是静态的。
而且我相信 JIT 需要的变量类型实际上是元数据标记指定的类。
重复警报
实际上它是重复的Richter 在描述非虚拟方法调用的内部结构时是否有误? https://stackoverflow.com/questions/4909373/is-richter-mistaken-when-describing-the-internals-of-a-non-virtual-method-call?rq=1
很高兴还有一个人和我有同样的问题。
引用的内容谈到了变量的类型,不属于变量引用的对象实例的类型。变量类型是静态已知的,因此所有决策都是静态的。
C# 编译器解析要调用的确切方法并将其编码到 IL 中。如果引用的程序集没有更改,则 JIT 本身不必执行任何方法解析。 C# 编译器这样做是因为它想要应用 C# 语义,而不是 CLR 语义。
要回答您编辑的问题:
- JIT 无法查看任何对象引用,因为它需要静态决定。它查看堆栈上元素的类型,无论该元素来自何处。在可验证的代码中,这是明确的。不过,变量类型不会影响方法绑定(IOW,你的问题 1 是不相关的)。
- 是的,方法是通过程序集+类型+方法名称和签名(包括)引用的。返回类型。非常精确。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)