在我的例子中,我使用的是 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
Write
方法的IL代码:
.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的MethodTable中应该只有DerivedClass.Method
。为什么调用 BaseClass.Method
? callvirt
是否在搜索方法时寻找特定的 override
标志?
最佳答案
因为您没有覆盖
它。将 new
更改为 override
,它将按照您讨论的方式运行(您还必须将可访问性更改为 protected
,否则它不会编译)。 new
创建一个不相关 方法,它恰好共享一个名称 - 它不是基类中其他同名方法的多态树的一部分。
你不妨问:“为什么这不调用 CompletelyDifferentName()
?”
class BaseClass
{
public void Write()
{
Method();
}
protected virtual void Method()
{
Console.WriteLine("Base - Method");
}
}
class DerivedClass : BaseClass
{
private void CompletelyDifferentName()
{
Console.WriteLine("Derived - Method");
}
}
答案是一样的:CompletelyDifferentName
与名为Method
的virtual
(多态)方法没有任何关系。好吧,new void Method()
也不是 - 这就是 new
的意思。
关于c# - `CallVirt` 和 `New` 关键字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18226425/