C#中编译器如何处理方法隐藏?父类引用调用隐藏方法的原理疑问
C# 中父类引用调用隐藏方法的底层逻辑
这个问题本质是C#对override重写和new隐藏两种语法的语义设计差异,和运行时能否识别对象实际类型无关,核心区别在于两者对虚方法表(vtable)的操作逻辑完全不同。
核心概念差异
- 重写(
override+virtual):是对基类虚方法表中同一槽位的实现替换。基类定义virtual方法时会在vtable中预留固定槽位,子类使用override关键字时,会直接替换子类vtable中该槽位的实现逻辑。运行时调用虚方法时,会直接取实际对象类型vtable对应槽位的实现,所以父类引用也能调用到子类的重写方法。 - 隐藏(
new):是在子类中声明完全独立的全新同名方法,和基类的同名方法没有继承关联,也不会修改基类方法在vtable中的原有槽位,只会在子类vtable中新增独立的槽位存储这个新方法的实现。
为什么父类引用调用不到子类的隐藏方法
父类引用的编译时类型决定了编译器能识别的vtable槽位范围:当你通过父类类型引用调用方法时,编译器只会根据父类的方法定义去匹配对应的vtable槽位,子类用new声明的隐藏方法不在父类的方法定义范围内,运行时自然找不到对应的实现,只会调用父类的原有方法。
代码示例验证
class BaseClass { public virtual void OverrideMethod() { Console.WriteLine("基类虚方法"); } public void HideMethod() { Console.WriteLine("基类普通方法"); } } class DerivedClass : BaseClass { // 重写:替换同一vtable槽位的实现 public override void OverrideMethod() { Console.WriteLine("子类重写的方法"); } // 隐藏:新增独立的同名方法 public new void HideMethod() { Console.WriteLine("子类隐藏的方法"); } } // 运行测试 public static void Main() { BaseClass obj = new DerivedClass(); obj.OverrideMethod(); // 输出:子类重写的方法 obj.HideMethod(); // 输出:基类普通方法 // 强转为子类类型后才能调用到隐藏方法 ((DerivedClass)obj).HideMethod(); // 输出:子类隐藏的方法 }
内容的提问来源于stack exchange,提问作者Samin Sadman Shad
相关产品推荐
相关产品推荐

