【问题标题】:Confused about "override" vs. "new" in C#对 C# 中的“覆盖”与“新”感到困惑
【发布时间】:2011-02-26 12:42:12
【问题描述】:

我正在上以下课程:

class Base
{
    public virtual void Print()
    {
        Console.WriteLine("Base");
    }
}

class Der1 : Base
{
    public new virtual void Print()
    {
        Console.WriteLine("Der1");
    }
}

class Der2 : Der1
{
    public override void Print()
    {
        Console.WriteLine("Der2");
    }
}

这是我的主要方法:

Base b = new Der2();
Der1 d1 = new Der2();
Der2 d2 = new Der2();

b.Print();
d1.Print();
d2.Print();

输出为BaseDer2Der2

据我所知,Override 不会让之前的方法运行,即使指针指向它们。所以第一行也应该输出Der2。不过Base出来了。

这怎么可能?覆盖如何在那里不起作用?

【问题讨论】:

  • Really An Amazing example... 这里唯一的技巧是:- 最初,BASE 的方法被“Der-1”的虚拟方法隐藏,因此覆盖“Der-2”的方法" 无法实施。因此,我们得到了 BASE 的值。

标签: c# virtual overriding new-operator


【解决方案1】:

您实际上从未覆盖过Base 版本的Print()。您只是在Der1 中使用单独的虚拟方法(名称相同)将其隐藏。

当您在方法签名上使用 new 关键字时 - 您是在告诉编译器这是一个恰好与您的一个基类的方法同名的方法 - 但没有其他关系。您可以将这个新方法设为虚拟(就像您所做的那样),但这与覆盖基类方法不同。

Der2 中,当您覆盖Print 时,您实际上是在覆盖您在Der1 中声明的“新”版本——而不是Base 版本。 Eric Lippert 有一个 excellent answer 来回答一个稍微不同的问题,这可能有助于您了解 C# 语言中如何处理虚拟方法。

在您的示例中,当您调用Print 时,您在第一种情况下通过Base 类型的引用调用它 - 因此调用Print 的隐藏(但不是覆盖)版本。其他两个调用被分派到Der1 的实现,因为在这种情况下,您实际上已经覆盖了该方法。

您可以在MSDN documentation of new and override 中阅读更多相关信息。

您可能打算对 Der1 执行的操作(就像您对 Der2 执行的操作一样)是使用 override 关键字:

class Base 
{ 
    public virtual void Print() 
    { 
        Console.WriteLine("Base"); 
    } 
} 

class Der1 : Base 
{ 
    // omitting 'new' and using override here will override Base
    public override void Print() 
    { 
        Console.WriteLine("Der1"); 
    } 
} 

【讨论】:

  • 这就是他对 Der2 所做的。
  • @GalacticCowboy - 确实,这就是我的观点。这可能也是 Der1 的意图,但不知何故,new 关键字被插入,而不是 override。我会更新我的帖子以使其更清楚。
  • 谢谢。一个很好的答案,我现在完全理解它是如何工作的。
  • 不管怎样,像这样的情况——以及它们引起的混乱——正是为什么编译器应该默认告诉你,“哦,只要把'new'就它...”(CS0108:msdn.microsoft.com/en-us/library/3s8070fc%28v=VS.80%29.aspx)因为那几乎是从不你真正想要做的。
【解决方案2】:

这是因为 Der1 没有覆盖 Print它用一个恰好具有相同名称的全新方法替换它(这是由使用new 关键字)。因此,当对象被转换为Base 时,它会在Base 中调用Print;没有覆盖调用..

【讨论】:

    【解决方案3】:

    override 将替换以前的方法,但是由于您的 Der1 类不会覆盖 Print()(它隐藏它,使用 VB-ism),所以 Base 的最覆盖版本调用Print(),恰好是它定义的版本

    【讨论】:

      【解决方案4】:

      正如大家所说,Der1 类正在替换 Print() 而不是覆盖它。要查看实际情况,您可以将 d1d2 设置为 Base,然后调用 print 方法。然后它将返回Base

      ((Base)d2).Print(); //Base
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-05-09
        • 2015-02-27
        • 1970-01-01
        • 2021-12-15
        • 2018-01-11
        • 1970-01-01
        • 2011-06-10
        • 2013-07-28
        相关资源
        最近更新 更多