8

考虑以下代码:

public abstract class Test1
{
    public object Data { get; set; }
}

public abstract class Test2<T> : Test1
{
    public T Data { get; set; }
}

这将生成以下警告:

“Test2.Data”隐藏了继承的成员“Test1.Data”。如果打算隐藏,请使用 new 关键字。

为什么这只是一个警告,添加“new”关键字会产生什么影响?

根据我的测试,一旦添加了“new”关键字,我就找不到任何区别。

不要误会我的意思,我完全是为了明确,但我很好奇添加“新”的好处。

我对它可能是什么的唯一想法是:

  • 提高人类可读性
  • 当编译器没有离开很长的路要解决不可避免的问题时,可以在运行时节省一些
4

4 回答 4

21

关键字的唯一作用new是删除警告。不使用new关键字时收到警告的目的是防止您在真正打算覆盖该方法时意外隐藏该方法。

于 2009-08-10T13:41:02.557 回答
3

new用于隐藏基类的方法或属性。这不像覆盖它:成员不需要与隐藏的基类成员具有相同的签名,并且不涉及多态性。

一个例子 :

class A
{
    public virtual void Test()
    {
        Console.WriteLine("A.Test");
    }
}

class B : A
{
    public new void Test()
    {
        Console.WriteLine("B.Test");
    }
}

class B : A
{
    public override void Test()
    {
        Console.WriteLine("C.Test");
    }
}

public static void Main(string[] args)
{
    A aa = new A();
    aa.Test(); // Prints "A.Test"

    A ab = new B();
    ab.Test(); // Prints "A.Test" because B.Test doesn't overrides A.Test, it hides it

    A ac = new C();
    ac.Test(); // Prints "C.Test" because C.Test overrides A.Test

    B b = new B();
    b.Test(); // Prints "B.Test", because the actual type of b is known at compile to be B
}
于 2009-08-10T13:48:54.763 回答
2

打开将警告报告为错误。这将迫使您更明确地使用 new 和 override。

于 2009-08-10T13:45:54.720 回答
1

派生类方法是否应被视为同名基类方法的覆盖通常取决于派生类方法的作者是否知道基类方法及其相关合同并编写派生类方法-class 方法来履行该合同。在大多数情况下,派生类方法与基类方法具有相同的名称和签名,派生类方法旨在履行基类契约,但如果部署的基类的作者添加了名称在没有意识到派生类中相同的名称用于其他目的的情况下,不能假定派生类方法作者编写了他的方法以符合当时不存在的基类方法的约定.

没有通用的方法可以让 C# 知道何时将不同的方法添加到类中,因此编译器无法知道派生类方法的作者是否知道类似名称的基类方法的存在除非new派生类方法的作者通过使用oroverride修饰符向编译器明确指出他是否知道基类方法的存在。

我建议将修饰符(或缺少修饰符)解释为:

  • 无——作者不知道基类方法的存在,因此不能期望履行其合同。

  • new-- 作者知道基类方法,并且出于某种原因编写了此方法,以免实现它。

  • override-- 作者知道基类方法和它的契约,写了这个方法来实现它。

编译器默认假设new但带有警告的原因是,如果在基类方法存在之前将该方法添加到派生类中,则不可能期望作者已经知道基类契约和不可能一直打算履行尚不存在的合同,但在派生类方法写在基类方法之后的情况下,作者通常应该选择另一个名称,除非作者打算履行基类方法-类合同或有特定原因使用相同名称而不履行合同。编译器无法判断哪个方法是先编写的,因此无法知道哪种行为是合适的。

于 2015-06-23T21:58:57.007 回答