C#和方法隐藏

时间:2009-07-23 07:20:58

标签: c# methods method-hiding

根据MSDN,用于方法隐藏的“new”关键字仅抑制警告。

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

我真的需要这个“new”关键字来执行方法隐藏吗?如果我有一个具有相同方法名但没有明确说明它是覆盖的子类,那本质上不是同一个东西,我只是得到一个警告?如果我的理解是正确的,请告诉我。感谢

9 个答案:

答案 0 :(得分:9)

无论是否指定“new”,都会隐藏方法,但它与覆盖不同。这是一个他们不同的例子:

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中的虚拟方法,并且这就是被执行的东西。

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

答案 1 :(得分:2)

隐藏(阴影)方法时应始终使用new关键字。虽然从技术上讲它并没有对功能产生影响,但正如你正确指出的那样,强烈建议这样做。

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

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

答案 2 :(得分:1)

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

我前段时间写过这篇文章,您可能需要阅读Method hiding or overriding - or the difference between new and virtual了解更多详情。

不应该阻止方法隐藏,因为它会改变类的语义。功能会根据您是否具有对基础或实际类的引用而更改。这是编译器发出警告的主要原因。如果调用者不知道正在使用方法隐藏,它可以做出意想不到的事情。

其他

根据问题的更新。方法隐藏不需要关键字new,但您应该将其设置为显式并使用关键字(如果您正在执行此操作)。它会删除编译器警告并提醒其他开发人员(或者您自己6个月后)的意图。

我仍然不建议隐藏方法,因为'

更新:14/5/11

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

答案 3 :(得分:1)

隐藏方法时使用new关键字是“使程序员的意图明确”。这可以避免程序员意外隐藏。

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

您可以阅读更多相关信息Versioning with the Override and New Keywords (C# Programming Guide)

答案 4 :(得分:1)

使用“new”和“not new new”之间的唯一区别是,当您不使用“new”关键字时,您将收到编译器警告,以提醒开发人员隐藏正在发生的任何无意方法。在以下网址中,您还可以找到一个很好的视频,解释method hiding and the difference between using "new" and "not using new"

答案 5 :(得分:0)

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

放置新关键字会强迫您考虑这是否真的是您打算做的,就像要求引用或退出一样,这样您就必须考虑代码提供的合同。

答案 6 :(得分: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中针对ClassA发出了警告,但未在ClassB中发出警告。但正如其他答案所述;不要混淆方法隐藏和方法重写的概念;不一样的。

答案 7 :(得分:0)

使用new是你想要一个同名的功能,但你不需要 想要覆盖。它打破了虚拟调度链。

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

答案 8 :(得分:0)

谢谢你们。我知道隐藏和覆盖之间的区别,我只是好奇,如果使用“新”和不使用“新”进行隐藏之间存在功能差异。根据你的所有答案,似乎并不是因为有人提出了一个好点,因为它使代码更清晰,而且将来可能是必要的。再次感谢民众!