You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

关于C#中new关键字阻断重写及多态调用结果的技术咨询

C#中new关键字阻断重写及多态调用结果的技术咨询

这是个非常经典的C#多态与new关键字的混淆问题,咱们一步步拆解清楚,先把代码贴出来方便对照:

public class A
{
    public virtual void Write() { Console.Write("A"); }
}
public class B : A
{
    public override void Write() { Console.Write("B"); }
}
public class C : B
{
    new public virtual void Write() { Console.Write("C"); }
}
public class D : C
{
    public override void Write() { Console.Write("D"); }
}

// ...
D d = new D();
C c = d;
B b = c;
A a = b;
d.Write();
c.Write();
b.Write();
a.Write();

为什么输出是DDBB而不是DDDD?

核心点要区分**override重写和new隐藏**的本质区别:

  • override是延续基类的虚拟方法链条,相当于在同一个“方法家族”里替换实现;
  • new是完全创建一个全新的虚拟方法,和基类的方法是两个独立的“家族”,只是名字相同而已。

咱们逐个梳理方法关系:

  1. A的Write()是第一个虚拟方法,开启了一个方法链条;
  2. B用override重写了A的Write(),相当于把这个链条的实现替换成了自己的,此时A/B类型的引用调用Write()都会走这个链条;
  3. C用new public virtual void Write(),这里的new直接切断了和B的Write()的关联——C的Write()是个全新的虚拟方法,和A/B的Write()没有任何重写关系。此时C的对象里其实同时存在两个Write():一个是继承自B的(属于A的链条),一个是自己的新方法;
  4. D用override重写的是C的新虚拟方法,完全没碰A/B那个链条的方法。

再看每个调用的执行逻辑:

  • d.Write():D类型引用直接调用自己重写的C的方法,输出D;
  • c.Write():C类型引用指向D对象,C的Write()是虚拟方法,D重写了它,所以调用D的实现,输出D;
  • b.Write():B类型引用指向D对象,此时调用的是A→B链条的Write(),而D根本没重写这个链条的方法,所以执行B的实现,输出B;
  • a.Write():A类型引用指向D对象,同样走A→B的链条,执行B的实现,输出B。

为什么实际对象是D,但b.Write()没有调用D的Write()?

因为D的Write()重写的是C的新方法,和B的Write()属于两个完全独立的方法体系。C用new关键字把自己的Write()和B的Write()彻底拆分开了,D并没有参与A→B那个方法链条的重写,所以当你用B类型的引用调用Write()时,只会识别到A→B链条的方法,和D重写的那个方法毫无关系。

备注:内容来源于stack exchange,提问作者Mike Lol

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.16 12:29:35