`

使用 Override 和 New 关键字进行版本控制(C# 编程指南)

    博客分类:
  • C#
 
阅读更多

使用 Override 和 New 关键字进行版本控制(C# 编程指南)

Visual Studio 2013
 
其他版本
 
7(共 8)对本文的评价是有帮助 评价此主题
 

 

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# 编程指南)

    了解何时使用 Override 和 New 关键字(C# 编程指南)

    new、abstract、virtual、override,sealed关键字区别和使用代码示例

    new、abstract、virtual、override,sealed关键字区别和使用代码示例

    C#中Override关键字和New关键字的用法详解

    C# 语言经过专门设计,以便不同库中的基类与派生类之间的版本控制可以不断向前发展,同时保持向后兼容。这具有多方面的意义。例如,这意味着在基类中引入与派生类中的某个成员具有相同名称的新成员在 C# 中是完全...

    C#教材及new关键字、委托事件理解

    1、C#系列教程 2、C#中new和override 3、C#中的try-catch语句使用方法 4、C#的各种连接数据库 5、c#中的委托和实践 6、C#的New关键字的几种用法

    深入理解C#中new、override、virtual关键字的区别

    下面小编就为大家带来一篇深入理解C#中new、override、virtual关键字的区别。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    c# override new base 关系

    c# override new base 关系

    C#几种关键字用法总结.zip

    C# 不安全代码关键字:unsafe、C# 关键字const 和 readonly、C# 关键字extern用法、C#关键字Fixed、C#关键字IntPtr、C#关键字之override详解、C#中DllImport用法汇总、C#中的IntPtr

    图解C# new和override的区别.doc

    图解C# new和override的区别.doc图解C# new和override的区别.doc图解C# new和override的区别.doc

    C++ override关键字使用详解

    主要介绍了C++ override关键字使用详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

    在一小时内学会 C#(txt版本)

    使用例程,简单却完整的探索 C# 语言的构造和特点。本文特别适合有 C++ 基础却没有太多精力学习 C# 的读者。 关于作者 Aisha Ikram 我现在在英国一家软件公司任技术带头人。我是计算机科学的硕士。我主要使用 ...

    C# 语言规范 版本5.0中文.pdf

    C# 的设计在某些方面直接考虑到版本控制的需要,其中包括单独使用的 virtual 和 override 修 饰符、方法重载决策规则以及对显式接口成员声明的支持。 本章的其余部分将描述 C# 语言的基本特征。尽管后面的章节会...

    new和override区别的小例子

    一个学习面向对象时常会问起的概念。通过一个小例子让你了解到C#动态绑定和静态绑定对于new和override区别的描述。

    C#中new和override的区别个人总结

    主要介绍了C#中new和override的区别个人总结,本文以问答的方式讲解了new和override的区别,需要的朋友可以参考下

    Visual C# 2010程序设计教程(教程PPT+源代码)

    主要内容包括.NET平台与Visual Studio 2010开发环境、C#语言基础及面向对象程序设计、C#程序设计、C# Web程序设计、C#泛型编程、C#数据库程序设计及ADO.NET等相关知识,并在最后讲解了运用C#处理文件和进行LINQ语言...

    C#编程实例代码集合

    Example011-使用任务栏的状态区 Example012-在运行时更新状态栏信息 Example013-无标题窗体的拖动 Example014-设置应用程序的图标 Example015-共享菜单项 Example016-动态设置窗体的光标 Example017-自己绘制菜单 ...

    Visual C# 2010程序设计教程PPT

    虚方法与override关键字 多态性 第9章 泛型编程 泛型的概念 泛型方法 泛型约束 使用泛型 第10章 windows应用程序开发 windows窗体开发基础 常用windows控件 windows菜单设计 工具...

    c#基础学习问答c#基础学习问答

    可以和 override 一起使用吗? 15.接口可以包含哪些成员? 16.类和结构的区别? 17.接口的多继承会带来哪些问题? 18.抽象类和接口的区别? 19.别名指示符是什么? 20.如何释放非托管资源? 21.P/Invoke是什么? 22....

    C# 4.0语言规范

    C# 的设计在某些方面直接考虑到版本控制的需要,其中包括单独使用的 virtual 和 override 修饰符、方法重载决策规则以及对显式接口成员声明的支持。 本章的其余部分将描述 C# 语言的基本特征。尽管后面的章节会更为...

Global site tag (gtag.js) - Google Analytics