使用 Override 和 New 关键字进行版本控制(C# 编程指南)
C# 语言经过专门设计,以便不同库中的基类与派生类之间的版本控制可以不断向前发展,同时保持向后兼容。 这具有多方面的意义。例如,这意味着在基类中引入与派生类中的某个成员具有相同名称的新成员在 C# 中是完全支持的,不会导致意外行为。 它还意味着类必须显式声明某方法是要重写一个继承方法,还是一个隐藏具有类似名称的继承方法的新方法。
在 C# 中,派生类可以包含与基类方法同名的方法。
-
基类方法必须定义为 virtual。
-
如果派生类中的方法前面没有 new 或 override 关键字,则编译器将发出警告,该方法将有如存在 new 关键字一样执行操作。
-
如果派生类中的方法前面带有 new 关键字,则该方法被定义为独立于基类中的方法。
-
如果派生类中的方法前面带有 override 关键字,则派生类的对象将调用该方法,而不是调用基类方法。
-
可以从派生类中使用 base 关键字调用基类方法。
-
override 、virtual 和 new 关键字还可以用于属性、索引器和事件中。
默认情况下,C# 方法为非虚方法。 如果某个方法被声明为虚方法,则继承该方法的任何类都可以实现它自己的版本。 若要使方法成为虚方法,必须在基类的方法声明中使用virtual 修饰符。 然后,派生类可以使用 override 关键字重写基虚方法,或使用 new 关键字隐藏基类中的虚方法。 如果 override 关键字和 new 关键字均未指定,编译器将发出警告,并且派生类中的方法将隐藏基类中的方法。
为了在实践中演示上述情况,我们暂时假定公司 A 创建了一个名为 GraphicsClass 的类,您的程序将使用此类。 GraphicsClass 如下所示:
class GraphicsClass { public virtual void DrawLine() { } public virtual void DrawPoint() { } }
您的公司使用此类,并且您在添加新方法时将其用来派生自己的类:
class YourDerivedGraphicsClass : GraphicsClass { public void DrawRectangle() { } }
您的应用程序运行正常,直到公司 A 发布了 GraphicsClass 的新版本,类似于下面的代码:
class GraphicsClass { public virtual void DrawLine() { } public virtual void DrawPoint() { } public virtual void DrawRectangle() { } }
现在,GraphicsClass 的新版本中包含一个名为 DrawRectangle 的方法。 开始时,没有出现任何问题。 新版本仍然与旧版本保持二进制兼容。 已经部署的任何软件都将继续正常工作,即使新类已安装到这些软件所在的计算机系统上。 在您的派生类中,对方法 DrawRectangle 的任何现有调用将继续引用您的版本。
但是,一旦您使用 GraphicsClass 的新版本重新编译应用程序,就会收到来自编译器的警告 CS0108。 此警告提示您必须考虑希望 DrawRectangle 方法在应用程序中的工作方式。
如果您希望自己的方法重写新的基类方法,请使用 override 关键字:
class YourDerivedGraphicsClass : GraphicsClass { public override void DrawRectangle() { } }
override 关键字可确保派生自 YourDerivedGraphicsClass 的任何对象都将使用 DrawRectangle 的派生类版本。 派生自 YourDerivedGraphicsClass 的对象仍可以使用基关键字访问 DrawRectangle 的基类版本:
base.DrawRectangle();
如果您不希望自己的方法重写新的基类方法,则需要注意以下事项。 为了避免这两个方法之间发生混淆,可以重命名您的方法。 这可能很耗费时间且容易出错,而且在某些情况下并不可行。 但是,如果您的项目相对较小,则可以使用 Visual Studio 的重构选项来重命名方法。 有关更多信息,请参见重构类和类型(类设计器)。
或者,也可以通过在派生类定义中使用关键字 new 来防止出现该警告:
class YourDerivedGraphicsClass : GraphicsClass { public new void DrawRectangle() { } }
使用 new 关键字可告诉编译器您的定义将隐藏基类中包含的定义。 这是默认行为。
当在类中指定方法时,如果有多个方法与调用兼容(例如,存在两种同名的方法,并且其参数与传递的参数兼容),则 C# 编译器将选择最佳方法进行调用。 下面的方法将是兼容的:
public class Derived : Base { public override void DoWork(int param) { } public void DoWork(double param) { } }
在 Derived 的一个实例中调用 DoWork 时,C# 编译器将首先尝试使该调用与最初在 Derived 上声明的 DoWork 版本兼容。 重写方法不被视为是在类上进行声明的,而是在基类上声明的方法的新实现。 仅当 C# 编译器无法将方法调用与 Derived 上的原始方法匹配时,它才尝试将该调用与具有相同名称和兼容参数的重写方法匹配。 例如:
int val = 5; Derived d = new Derived(); d.DoWork(val); // Calls DoWork(double).
由于变量 val 可以隐式转换为 double 类型,因此 C# 编译器将调用 DoWork(double),而不是 DoWork(int)。 有两种方法可以避免此情况。 首先,避免将新方法声明为与虚方法同名。 其次,可以通过将 Derived 的实例强制转换为 Base 来使 C# 编译器搜索基类方法列表,从而使其调用虚方法。 由于是虚方法,因此将调用 Derived 上的DoWork(int) 的实现。 例如:
((Base)d).DoWork(val); // Calls DoWork(int) on Derived.
有关 new 和 override的更多示例,请参见 了解何时使用 Override 和 New 关键字(C# 编程指南)。
相关推荐
### 了解何时使用 Override 和 New 关键字(C# 编程指南) #### 概述 在面向对象的编程语言中,尤其是 C# 这种强类型语言里,继承是实现代码复用的一种常见方式。当一个类继承自另一个类时,它不仅可以重用基类的...
#### 十七、使用Override和New关键字进行版本控制 - **Override关键字**:用于重写基类中的虚方法。 - **New关键字**:用于隐藏基类中的方法或属性。 #### 十八、了解何时使用Override和New关键字 - **选择标准**:...
本资源是一个详细的C#编程指南,来自MSDN,涵盖了C#的各个方面,从类和对象到结构和继承。下面是该资源的知识点总结: 一、类(C# 编程指南) * 类是C#中的基本构成单元,用于定义对象的行为和状态。 * 类可以包含...
- 多态:接口和抽象类实现动态绑定,以及override和new关键字的使用。 - 接口:定义行为规范,实现多继承效果。 - 集合:如List、Dictionary, TValue>等,用于存储和操作数据。 3. **高级特性** - 枚举和结构:...
《Visual Basic.NET 面向对象编程指南》是一本深入探讨如何使用Visual Basic.NET进行面向对象编程的书籍。随书附带的光盘源码包含了多个章节的实例代码,包括ch09、ch02、ch05、ch10、ch08、ch04和ch07等子文件夹,...
### 调高C#编程的50个基本技巧 #### 1. 总是用属性(Property)来代替可访问的数据成员 在C#中,属性提供了一种封装数据成员的方式,使得我们可以像访问公共字段一样简单地读取或设置私有字段。这样做的好处是可以...
- 使用Git进行版本控制。 - Visual Studio中的团队项目管理和代码合并。 #### 十四、C#生态系统与资源推荐 - **社区与资源**: - 推荐学习网站:Microsoft Learn、Stack Overflow、GitHub等。 - 参与开源项目...
《微软C#语言参考》是面向C#编程者的一本权威指南,旨在帮助读者深入理解和掌握C#这一强大且广泛使用的编程语言。这本书受到了广大读者的高度评价,是C#学习者的重要参考资料。以下是对该书内容的详细解读: C#(读...
根据给定的文件标题、描述、标签以及部分内容,本文旨在为有一定 C++ 基础但没有太多时间深入学习 C# 的读者提供一个快速入门指南。以下是对文章中提到的关键知识点的详细阐述: ### 一小时内学会 C# 的核心概念 #...
《Professional C# 2008 36-38》是针对C#编程语言的一本专业指南,涵盖了2008年版本的C#语言特性和开发实践。该书的第36到38章提供了丰富的代码示例,帮助读者深入理解C#的核心概念和技术。以下是基于这些章节的代码...
- **new**:隐藏基类中的方法或字段,可以在派生类中使用new关键字隐藏基类中同名的方法或字段。 - **2.5 值类型、引用类型的区别** - **值类型**:存储在栈中,直接包含数据。 - **引用类型**:存储在堆中,...
通过本文的详细介绍和代码示例,读者应能深刻理解结构体的基本概念,并学会如何在C#编程中合理使用它们。结构体作为C#中的一种非常有用的数据类型,非常适合创建轻量级、高性能的数据结构。掌握了这些知识后,你将在...
《C# 完全手册》是一本全面深入讲解C#编程语言的权威指南,适合所有层次的开发者学习。这本书不仅涵盖了C#的基础知识,还深入探讨了.NET框架以及C#在实际开发中的应用。以下是对书中关键知识点的详细阐述: 1. **C#...
根据提供的文件信息,我们可以整理出一系列关于C#编程语言中的编码标准及最佳实践。下面将对这些要点进行详细的解释和扩展: ### 1. 文件结构与布局 - **每个文件只包含一个类**:为了保持代码的清晰度和可维护性,...
### C#完全手册知识点概览 ...- **新属性**:使用new关键字隐藏基类中的属性。 **14.5 小结** - 继承和多态是面向对象编程的核心,它们增强了代码的灵活性和可扩展性。 #### 十五、接口 **15.1 组件编程技术** - ...
34. **覆盖方法**:在派生类中使用`override`关键字重写基类的方法,而非简单地使用`new`。 35. **密封类与虚方法**:如果一个类不打算被继承,则使用`sealed`关键字;如果希望某个方法可以被重写,则应声明为`...
### .NET Core Worker Service的C#实现与优化:全方位实践指南 #### 一、项目创建与初始化 在开始实现.NET Core Worker Service之前,首先需要创建一个新的.NET Core项目。这一过程可以通过多种方式完成: 1. **...
C#是一种广泛应用于桌面应用、游戏开发、...以上仅是C#编程语言部分核心知识点的概述,实际的C-Sharp-Cheatsheet会更深入地介绍这些概念,并可能包括实例代码和实用技巧,帮助开发者快速查阅和理解C#语言的各种特性。