新关键字隐藏虚拟方法实现的实际用途是什么? c#

6

在派生类中使用new关键字为虚方法提供新实现的真实场景是什么?C#

我知道它在技术上意味着什么。我想要的是一个实际的场景,在这种情况下,需要使用此功能。

我们总是可以通过提供override功能来实现相同的效果。为什么当方法调用被转换为基础时,我们希望选择不正确的方法。


最好在http://programmers.stackexchange.com/上进行讨论。 - Shamim Hafiz - MSFT
3个回答

5

不,你不能通过覆盖来实现相同的功能:

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

一个示例场景:

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

此时,您希望所有调用Bar.DoSomething的现有代码仍然调用Bar.DoSomething,但调用Foo.DoSomething的所有代码仍然调用该实现-这些调用者甚至可能不知道您的方法,并且它们可能在第三方程序集中。

从长远来看,在这种情况下,您可能需要重命名自己的方法(取决于您对调用者的控制程度),但在短期内,将您的方法设置为new可以实现您想要的行为。

这种情况有时被称为“脆弱的基类”问题。Eric Lippert对此进行了相当广泛的写作,包括在2004年的这篇文章中提到的内容。

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.");
    }
}

现在,如果你尝试这样做:
public static void TestCars2()
{
    Car[] cars = new Car[3];
    cars[0] = new Car();
    cars[1] = new ConvertibleCar();
    cars[2] = new Minivan();
}

结果将是:
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.

----------

覆盖(Override)始终覆盖,而新建(New)仅在其声明类型(不是基类类型)下使用时才这样做。

您可以在此处查看更多信息


1
我正在寻找真实的场景,而这个是为了书而写的。无论如何,Jon提供的脆弱基础情境回答了它。 - ParvindS
这不是需要示例的情况。 - Deepak Mishra

0
虚方法可以被重新定义。虚关键字指定了一个在派生类中被覆盖的方法。我们可以添加派生类型而不修改程序的其余部分。因此,对象的运行时类型决定了它的行为。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接