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

时间:2011-07-29 06:28:49

标签: c# override virtual new-operator

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

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

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

3 个答案:

答案 0 :(得分: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.

----------

覆盖ALWAYS覆盖,而新的ONLY在用作声明类型(而不是基础代码)时进行覆盖。

你可以see more here

答案 1 :(得分:5)

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

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

一个示例场景:

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

此时,您希望所有现有代码调用Bar.DoSomething到仍然调用Bar.DoSomething,但所有调用Foo.DoSomething的代码仍应调用那个实现 - 那些调用者甚至可能知道你的方法,他们可能在第三方程序集中。

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

这种事情有时被称为脆弱的基类问题。 Eric Lippert已经合理地撰写了相关文章,包括this post back in 2004

答案 2 :(得分:0)

可以重新定义虚拟方法。 virtual关键字指定在派生类中重写的方法。我们可以添加派生类型而无需修改程序的其余部分。因此,运行时类型的对象决定了行为。