现实生活中使用新关键字隐藏虚拟方法实现?C#

Par*_*ndS 6 c# virtual overriding new-operator

我们将使用new为派生类中的虚方法提供新实现的真实场景是什么?C#

我知道这在技术上意味着什么.我正在寻找的是一个真实的生活场景,需要这样做.

我们总是可以通过提供覆盖功能来实现相同的目标.当方法调用被转换为base时,为什么我们想要选择不正确的方法.

Err*_*Efe 5

不,你不可能实现同样的目标.

// Define the base class
class Car
{
    public virtual void DescribeCar()
    {
        System.Console.WriteLine("Four wheels and an engine.");
    }
}

// Define the derived classes
class ConvertibleCar : Car
{
    public new virtual void DescribeCar()
    {
        base.DescribeCar();
        System.Console.WriteLine("A roof that opens up.");
    }
}

class Minivan : Car
{
    public override void DescribeCar()
    {
        base.DescribeCar();
        System.Console.WriteLine("Carries seven people.");
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,如果您尝试这样做:

public static void TestCars2()
{
    Car[] cars = new Car[3];
    cars[0] = new Car();
    cars[1] = new ConvertibleCar();
    cars[2] = new Minivan();
}
Run Code Online (Sandbox Code Playgroud)

结果将是:

Car object: YourApplication.Car

Four wheels and an engine.

----------

Car object: YourApplication.ConvertibleCar

Four wheels and an engine.

----------

Car object: YourApplication.Minivan

Four wheels and an engine.

Carries seven people.

----------
Run Code Online (Sandbox Code Playgroud)

覆盖ALWAYS覆盖,而新的ONLY在用作其声明的类型(不是基础的)时执行.

你可以在这里看到更多


Jon*_*eet 5

不,你不能通过覆盖达到同样的目的:

  • 指定新方法允许您更改返回类型
  • 调用基本方法可能不正确

一个示例场景:

  • 你正在使用第三方库Foo,它包含一个类FooBase
  • 你编写自己的Foo,Bar子类
  • 您在Bar中引入了一个名为DoSomething的公共方法
  • 在Foo的下一个版本中,第三方在Foo中引入了DoSomething方法,该方法与您的方法不同.这可能是也可能不是虚拟的.

此时,您希望调用Bar.DoSomething的所有现有代码仍然调用Bar.DoSomething,但调用Foo.DoSomething的所有代码仍应调用该实现 - 这些调用者可能甚至不知道您的方法,他们可能是在第三方集会.

从长远来看,如果可以的话,您可能希望重命名您的方法(取决于您对调用者的控制程度),但在短期内,使您的方法new完全符合您想要的行为.

这类事情有时被称为脆弱的基类问题.Eric Lippert已经相当广泛地撰写了这篇文章,包括2004年的这篇文章.