C#方法重写(Override)与隐藏(New)的区别及示例
在C#面向对象编程中,子类继承父类时如何处理同名方法是关键知识点。文章深入对比了方法重写(Override)与方法隐藏(New)的本质区别,结合多态场景下的代码执行结果,清晰阐述了虚函数表调用与非虚函数的静态绑定差异,帮助开发者规避命名冲突带来的逻辑错误。
核心概念辨析
C#提供了两种机制来处理派生类中与基类同名或同签名的方法,它们的底层机制和行为表现截然不同:
- 方法重写 (Override):必须要求基类方法标记为
virtual、abstract或override。派生类使用override关键字替换基类的实现。此时,原方法在基类层面被完全取代。当发生多态调用(基类引用指向派生类对象)时,系统将运行时的实际类型来决定执行哪个版本的方法,这是多态性的典型体现。 - 方法隐藏 (Hide):无论基类方法是否为虚方法,派生类都可以使用
new关键字来“隐藏”基类方法。与原方法被彻底覆盖不同,基类中的方法依然存在且未被删除。如果不用new关键字直接定义同名方法,编译器会发出警告(Warning),提示该方法隐藏了继承成员。
第1步:构建包含重写与隐藏的基类与派生类
首先定义基类 BaseClass,其中包含一个普通方法 functionA 和一个虚方法 functionB。随后在派生类 DerivedClass 中分别对这两个方法进行 new 隐藏和 override 重写。
public class BaseClass
{
public void functionA()
{
Console.WriteLine("BaseFunctionA");
}
public virtual void functionB()
{
Console.WriteLine("BaseFunctionB");
}
}
public class DerivedClass : BaseClass
{
public new void functionA()
{
Console.WriteLine("DerivedFunctionA");
}
public override void functionB()
{
Console.WriteLine("DerivedFunctionB");
}
}
第2步:利用多态性验证执行结果
为了直观观察两者的区别,我们创建一个典型的“向上转型”场景:声明一个基类类型的变量,但实例化一个派生类对象。这种写法常用于依赖倒置等设计模式中,重点在于考察方法的动态分发机制。
代码操作入口:Program.cs 主程序
关键动作:实例化对象并通过基类引用调用方法
BaseClass baseObj = new DerivedClass();
baseObj.functionA();
baseObj.functionB();
结果分析与原理解读
上述代码的实际输出结果如下:
BaseFunctionA
DerivedFunctionB
这里发生了两件事,验证了前文所述的区别:
functionA的静态绑定:尽管实际对象是DerivedClass,但因为functionA只是被new隐藏,并未参与多态重写,所以调用时遵循编译时类型。编译器看到BaseClass类型的引用,因此直接调用了基类的BaseFunctionA。派生类的逻辑被“静默”忽略。functionB的动态绑定:由于functionB使用了virtual和override,它成为了多态的一部分。在运行时,CLR(公共语言运行时)检查对象的实际类型(即DerivedClass),从而正确调用派生类重写的DerivedFunctionB。
开发最佳实践建议
- 优先选择 Override:在设计继承体系时,如果希望子类能够改变父类的行为逻辑以实现多态,务必使用
virtual+override模式。这是OOP(面向对象编程)的标准做法。 - 慎用 New:除非你明确知道自己在做什么(例如为了避免破坏原有API签名同时添加新功能),否则不建议随意使用
new隐藏方法。这不仅容易让阅读者产生误解,也可能在多态调用场景中导致难以排查的逻辑缺陷。 - 消除编译警告:如果你确实需要使用
new,请显式加上关键字,以消除编译器的“此结构可能隐藏另一个结构”警告,这能向其他维护代码的程序员传达明确的意图。
以上就是C#方法重写和隐藏的详细教学内容,更多关于C#面向对象高级特性的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









