2

我一直在阅读 c# 规范,遇到了一个我没想到的场景,并希望有人能分享一些启示。

我偶然发现了new在派生类中隐藏基类成员的关键字,随后就何时使用new而不是overrideonvirtual成员进行了一些讨论。

我在我的 IDE 中扔了一个小代码示例,期望看到一个编译错误

public class BaseType
{
    public void method()
    {
        // do nothing
    }
}
public class DerivedType : BaseType
{
    public new void method()
    {
        base.method();
    }
}

但相反发现这是合法的c#。既然派生类已经隐藏了 的存在method(),为什么还允许我调用呢?

干杯

4

2 回答 2

3

DerivedType方法从将要继承的类中隐藏起来DerivedType,而不是从其自身中隐藏。
请注意,要隐藏该方法,该类必须知道其父类中存在一个具有相同名称和相同参数的方法。因此,一个类将方法隐藏在它自己的范围之外是不合逻辑的。

于 2014-08-18T11:58:27.897 回答
2

不要将方法隐藏与方法覆盖混为一谈。他们是两种完全不同的野兽。

隐藏方法时,仅在通过隐藏方法开头的类型访问方法时才隐藏它:

public class Foo
{
    public string Blah() { return "Hi from Foo!"; }
}

public class DerivedFoo: Foo
{
    public new string Blah() { return "Hi from DerivedFoo!"; }
}

现在我们有以下行为:

void TestFoos()
{
    Foo foo = new Foo();
    DerivedFoo derivedFoo = new DerivedFoo();
    Foo derivedFooInDisguise = derivedFoo as Foo;

    Console.WriteLine(foo.Blah()); //Outputs "Hi from Foo!"
    Console.WriteLine(derivedFoo.Blah()); //Outputs "Hi from DerivedFoo!"
    Console.WriteLine(derivedFooInDisguise.Blah()); //Outputs "Hi from Foo!" 
}

请注意,即使Blah声明为,此行为也是相同的virtual。有趣的部分是第三个调用。该方法通过Foo类型化对象调用。由于它不是虚拟调用,Foo.Blah()因此被调用,而不是DerivedFoo.Blah().

现在这与方法覆盖完全不同,其中虚拟方法调用始终解析为对象的运行时类型,而不是您调用它的类型:

public class Foo
{
    public virtual string Blah() { return "Hi from Foo!"; }
}

public class DerivedFoo: Foo
{
    public override string Blah() { return "Hi from DerivedFoo!"; }
}

现在我们有以下行为:

void TestFoos()
{
    Foo foo = new Foo();
    DerivedFoo derivedFoo = new DerivedFoo();
    Foo derivedFooInDisguise = derivedFoo as Foo;

    Console.WriteLine(foo.Blah()); //Outputs "Hi from Foo!"
    Console.WriteLine(derivedFoo.Blah()); //Outputs "Hi from DerivedFoo!"
    Console.WriteLine(derivedFooInDisguise.Blah()); ////Outputs "Hi from DerivedFoo!"
} 
于 2014-08-18T12:11:37.013 回答