C# 中的 override 和 new 关键字有啥区别?

Posted

技术标签:

【中文标题】C# 中的 override 和 new 关键字有啥区别?【英文标题】:What is the difference between the override and new keywords in C#?C# 中的 override 和 new 关键字有什么区别? 【发布时间】:2011-09-28 09:44:18 【问题描述】:

在类层次结构中定义方法时,C# 中的overridenew 关键字有什么区别?

【问题讨论】:

【参考方案1】:

以下页面很好地总结了您的问题。

Knowing When to Use Override and New Keywords

总结

重写:当基类的方法在派生类中被重写时,将使用派生类中的版本,即使调用代码不“知道”该对象是派生类的一个实例。

新建:如果使用new关键字代替override,派生类中的方法不会覆盖基类中的方法,它只是隐藏它。

如果您没有指定 new 或 overrides,则结果输出与您指定 new 时相同,但您也会收到编译器警告(因为您可能不知道您在基类方法,或者实际上您可能想要覆盖它,只是忘记包含关键字)。

覆盖:与基类中的虚拟/抽象/覆盖类型的方法一起使用

新增:当基类没有将方法声明为虚拟/抽象/覆盖时

【讨论】:

您能否在此处也包含重要信息。它有助于将信息保留在这里并防止链接失效(不太可能与 MSDN 博客,但你永远不知道)。 大声笑“不太可能”我收到重定向,然后是“拒绝访问您没有查看/下载此项目的权限。”【参考方案2】:

new 将使用全新的方法(可能具有或不具有相同的签名)覆盖该方法,而不是覆盖它(在这种情况下,新方法必须具有相同的签名),这意味着多态不会工作。例如,您有这些类:

class A 
    public virtual int Hello() 
        return 1;
    


class B : A 
    new public int Hello(object newParam) 
        return 2;
    


class C : A 
    public override int Hello() 
        return 3;
    

如果你这样做:

A objectA;
B objectB = new B();
C objectC = new C();

Console.WriteLine(objectB.Hello(null)); // 2
Console.WriteLine(objectC.Hello()); // 3

objectA = objectB;

Console.WriteLine(objectA.Hello()); // 1

objectA = objectC;

Console.WriteLine(objectA.Hello()); // 3

由于您可以使用new 定义新方法签名,因此编译器不可能知道A 的实例实际上是B 的实例,并且应该可以使用新方法B 定义。 new 可以在父对象的方法、属性、字段或事件未使用virtual 声明时使用,并且由于缺少virtual,编译器不会“查找”继承的方法。但是,对于 virtualoverride,它可以工作。

我强烈建议您避免使用new;充其量是令人困惑的,因为您定义的方法的名称可能会被识别为其他东西,而在最坏的情况下,它可以隐藏错误,引入看似不可能的错误,并使扩展功能变得困难。

【讨论】:

这应该是公认的答案。它实际上通过示例解释了差异和含义。接受的答案非常模糊。 在使用接口时会发生类似的情况(如 B 扩展 A,A 用Hello() 实现接口,将 B 分配给具有接口类型的变量)。最好在您的回答中澄清这一点,因为这就是我正在寻找的情况。【参考方案3】:

看起来像一个老问题,让我尝试一个不同的答案:

    new :顾名思义,它是继承层次结构家族中的一个新成员,它将用作更下游的基础成员(如果标记为虚拟)。

    override :这意味着我不接受我的父类的成员实现,我会做不同的事情。

【讨论】:

【参考方案4】:

考虑以下类层次结构:

using System;

namespace ConsoleApp
     
     public static class Program
        
          public static void Main(string[] args)
              
               Overrider overrider = new Overrider();
               Base base1 = overrider;
               overrider.Foo();
               base1.Foo();

               Hider hider = new Hider();
               Base base2 = hider;
               hider.Foo();
               base2.Foo();
             
        

     public class Base
     
         public virtual void Foo()
         
             Console.WriteLine("Base      => Foo");
         
     

     public class Overrider : Base
     
         public override void Foo()
         
             Console.WriteLine("Overrider => Foo");
         
     

     public class Hider : Base
     
         public new void Foo()
         
             Console.WriteLine("Hider     => Foo");
         
     
    

以上代码的输出必须是:

Overrider => Foo
Overrider => Foo

Hider     => Foo
Base      => Foo
子类overrides通过应用override modifier实现虚方法: 如果你想故意hide一个成员,在这种情况下你可以将new modifier应用于子类中的成员。 The new modifier does nothing more than suppress the compiler warning that would otherwise result

【讨论】:

很好的例子,我认为如果你将Program 类和其他类分成两个单独的代码块,输出与方法调用内联作为注释,例如base2.Foo(); // Base => Foo。我也会省略命名空间和导入,但如果你想提供可运行的代码,那么只需链接到 dotnetfiddle.net【参考方案5】:

override 允许您覆盖基类中的虚拟方法,以便您可以放入不同的实现。new 将隐藏基类中的非虚拟方法。

【讨论】:

我知道的就这么多了,但是 override 将有效地隐藏基类方法 没有覆盖不会隐藏基类方法。 Override 将对基类方法的调用转换为对派生类方法的调用。在某种程度上,派生类中的方法与基类中的方法相同。而对于new,它是一个完全独立的方法,只是恰好具有相同的名称。 @CodeInChaos 感谢您说出我想说的比我能说的更好:)【参考方案6】:

简单的区别在于override 表示该方法是虚拟的(它与基类中的virtual 关键字进行传导),而new 仅表示它不是虚拟的,它是一个常规覆盖。

所以两者都是真正的函数覆盖,一个是具有虚拟特性的,另一个不是。

具体是什么意思?它只是意味着多态性不会在“新”方法中发挥作用。

下面的图片说明可能会清楚地说明这一点。

注意如果你不使用new关键字,它仍然是隐含的,但它会产生一个警告信息。

【讨论】:

以上是关于C# 中的 override 和 new 关键字有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

C#简述override和overload的区别

new在c#方法中的使用

c#基础-19.重写(override)和覆盖(new)的区别

30天C#基础巩固------this,base,string中的方法,StringBuilder性能

C# 实例:重写(override)

C# 中基类,虚类,抽象类,密封类,接口的区别