5

Per MSDN, the "new" keyword when used for method hiding only suppresses a warning.

http://msdn.microsoft.com/en-us/library/435f1dw2.aspx

Do I really need this "new" keyword to perform method hiding? If I have a child class that has the same method name but doesn't explicitly state that it is overriding, isn't that the same thing essentially, I just get a warning? Please tell me if my understanding is correct. Thanks

4

9 回答 9

9

无论您是否指定“新”,您都会隐藏方法,但这与覆盖不同。这是它们不同的示例:

using System;

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

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

class Derived : Base
{
    public override void OverrideMe()
    {
        Console.WriteLine("Derived.OverrideMe");
    }

    public new void HideMe()
    {
        Console.WriteLine("Derived.HideMe");
    }
}

class Test
{
    static void Main()
    {
        Base x = new Derived();
        x.OverrideMe();
        x.HideMe();
    }
}

输出是:

Derived.OverrideMe
Base.HideMe

即使基本HideMe方法是虚拟的,它也没有被覆盖Derived,它只是被隐藏了——所以该方法仍然绑定到虚拟方法Base,这就是被执行的。

成员隐藏通常是一个坏主意,使代码更难理解。然而,它可用的事实在版本控制方面是有益的 - 这意味着向基类添加方法不会潜在地让派生类无意中覆盖它,并且它们可以像以前一样继续工作。这就是你收到警告的原因。

于 2009-07-23T07:28:52.303 回答
3

new隐藏(遮蔽)方法时应始终使用关键字。尽管从技术上讲它对功能没有影响,但正如您正确指出的那样,强烈建议您这样做。

关键字的出现不仅向代码的读者清楚地表明您在基类中显式隐藏了同名方法,而且它的用法是官方(MSDN)C#指南的一部分,很可能是因为它将来可能需要使用。

当前编译器仅在您省略关键字时给您警告(而不是错误)的原因纯粹是出于向后兼容性的原因。正如 MSDN 建议的那样, C# 1.0 不支持隐藏new类成员的关键字,然后自动执行方法(通常是成员)隐藏。我怀疑 MS 会尝试在这方面保持向后兼容性,但在未来的 C# 版本中肯定不能保证。

于 2009-07-23T07:29:03.987 回答
1

使用“new”和“not using new”的唯一区别是,当你不使用“new”关键字时,你会得到一个编译器警告,提醒开发人员任何无意中隐藏的方法正在发生。在以下 URL,您还可以找到一个出色的视频,解释方法隐藏以及使用“新”和“不使用新”之间的区别

于 2012-06-12T21:16:25.083 回答
1

在隐藏方法时使用 new 关键字是为了“使程序员的意图清晰”。这避免了程序员的意外隐藏。

如果新关键字不存在,则编译器会发出警告并将其视为存在。

您可以阅读更多关于使用 Override 和 New 关键字进行版本控制的信息(C# 编程指南)

于 2009-07-23T07:52:47.090 回答
1

方法隐藏与覆盖不同。不要在应该选择覆盖的地方使用它,因为它们的工作方式不同。

我前段时间写过这篇文章,您可能想阅读Method hidden or overriding - 或 new 和 virtual 之间的区别以了解更多详细信息。

不鼓励方法隐藏,因为它会改变类的语义。功能的变化取决于您是否引用了基类或实际类。这是有编译器警告的主要原因。如果调用者不知道正在使用方法隐藏,它可能会做意想不到的事情。

额外的

基于对问题的更新。方法隐藏不需要关键字new,尽管您应该明确说明并使用关键字,如果您正在这样做的话。它消除了编译器警告并提醒其他开发人员(或您自己 6 个月后)您的意图是什么。

我仍然不推荐方法隐藏,虽然'

更新:11 年 14 月 5 日

我移动了我的博客,所以我正在更新所有旧链接

于 2009-07-23T07:25:16.927 回答
0

多谢你们。我知道隐藏和覆盖之间的区别,我只是好奇使用“new”和不使用“new”进行隐藏之间是否存在功能差异。根据您的所有答案,尽管有人提出了一个很好的观点,因为它可以使代码更简洁,并且将来可能有必要,但似乎并非如此。再次感谢各位!

于 2009-07-23T08:08:37.403 回答
0

它是 C# 的一部分,就像 ref 和 out 一样。这个想法是警告您您的 API 正在覆盖一个可能影响依赖于您的类的子/超类的代码的方法。

放置 new 关键字会迫使您考虑这是否真的是您打算做的,就像要求 ref 或 out 一样,因此您必须考虑代码提供的合同。

于 2009-07-23T07:24:57.380 回答
0

据我所知,唯一的区别是你建议的new那个:隐藏警告。我尝试了以下代码:

class Base
{
    public void Test(){}
}

class ChildA : Base
{
    public void Test(){}
}


class ChildB : Base
{
    public new void Test(){}
}

两个类的测试方法在 IL 中看起来相同:

.method public hidebysig instance void  Test() cil managed
{
  // Code size       1 (0x1)
  .maxstack  8
  IL_0000:  ret
} // end of method ChildA::Test

.method public hidebysig instance void  Test() cil managed
{
  // Code size       1 (0x1)
  .maxstack  8
  IL_0000:  ret
} // end of method ChildB::Test

Test编译器对in发出警告ClassA,但不在 in 中ClassB。但正如其他答案所述;不要混淆方法隐藏和方法覆盖的概念;不是一回事。

于 2009-07-23T07:28:10.823 回答
0

new 的使用是当你想要一个同名的函数,但又不想覆盖时。它打破了虚拟调度链。

当有人将函数添加到与派生类函数同名的基类时,可能会发生这种情况。

于 2009-07-23T07:28:54.597 回答