这个问题链接到当引用存储在基类变量中时,CLR 如何调用派生类正确隐藏的方法?
就我而言,我使用的是callvirt
指令,而不是call
class BaseClass
{
public void Write()
{
Method();
}
protected virtual void Method()
{
Console.WriteLine("Base - Method");
}
}
class DerivedClass : BaseClass
{
private new void Method()
{
Console.WriteLine("Derived - Method");
}
}
static void Main(string[] args)
{
DerivedClass dc = new DerivedClass();
BaseClass bcdc = new DerivedClass();
dc.Write();
bcdc.Write();
Console.ReadKey(true);
}
输出:
Base - Method
Base - Method
方法的IL代码Write
:
.method public hidebysig instance void Write() cil managed
{
// Code size 9 (0x9)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: callvirt instance void Private_override.Program/BaseClass::Method()
IL_0007: nop
IL_0008: ret
} // end of method BaseClass::Write
我不明白这里为什么Base
调用方法。
这里 CLR 使用callvirt
指令,这意味着它将查找调用变量类型,并且由于类型是DerivedClass
和DerivedClass
隐藏的BaseClass.Method
,因此应该只存在DerivedClass.Method
于堆中的 DerivedClass 的 MethodTable 中。为什么BaseClass.Method
叫?搜索方法时是否callvirt
查找特定标志?override