c# - C# 允许在虚拟方法上使用 new 的用例是什么?

标签 c#

作为主要的 Java 开发人员,有一天我不小心使用了 new 关键字而不是 override,结果让我感到有点惊讶。

看起来 new 关键字删除了继承树中该级别方法的“虚拟性”,因此在向下转换为父类的子类实例上调用方法, 不会解析到子类中的方法实现。

此行为的实际用例是什么?

澄清:我理解当父级不是虚拟时使用 new。我更好奇为什么编译器允许 new 和 virtual 结合。

下面的例子说明了区别:

using System;

public class FooBar
{
    public virtual void AAA()
    {
        Console.WriteLine("FooBar:AAA");
    }

    public virtual void CCC()
    {
        Console.WriteLine("FooBar:CCC");
    }
}

public class Bar : FooBar
{
    public new void AAA()
    {
        Console.WriteLine("Bar:AAA");
    }

    public override void CCC()
    {
        Console.WriteLine("Bar:CCC");
    }
}

public class TestClass
{
    public static void Main()
    {
        FooBar a = new Bar();
        Bar b = new Bar();
        Console.WriteLine("Calling FooBar:AAA");
        a.AAA();
        Console.WriteLine("Calling FooBar:CCC");
        a.CCC();
        Console.WriteLine("Calling Bar:AAA");
        b.AAA();
        Console.WriteLine("Calling Bar:CCC");
        b.CCC();
        Console.ReadLine(); 
    }
}

这会产生以下输出:

Calling FooBar:AAA
FooBar:AAA
Calling FooBar:CCC
Bar:CCC
Calling Bar:AAA
Bar:AAA
Calling Bar:CCC
Bar:CCC

最佳答案

用例:

  • 今天,您使用第 3 方库并从类 Fruit 派生类 Banana
  • 您在 Banana 中实现了一个名为 Peel 的方法。 Fruit 中没有Peel
  • 明天,第 3 方将发布新版本的库,包括一个虚拟的 Fruit.Peel 方法
  • 你明天重新编译你的代码。你想覆盖 Fruit.Peel 吗?很可能不是——它可能有完全不同的含义。相反,您可以使用 Banana.Peel隐藏它,并且所有现有代码都像今天一样工作。

换句话说,这主要是为了避免版本控制问题。在 Java 中,您最终会重写 Fruit.peel,即使您不想这样做,很可能导致难以诊断的错误。

关于c# - C# 允许在虚拟方法上使用 new 的用例是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1472701/

相关文章:

c# - 将无效字符解析为 XML

c# - 如何保存附件?

c#关于接口(interface)

c# - 从类库加载部分

c# - 为什么 C# 区分大小写?

c# - 使用 Xamarin.Android 为 Parse.com 服务器制作更漂亮的 Facebook 登录屏幕

c# - 计算数据网格上的行并将其添加为新列

c# - 使用 EPPlus 将问题写入电子表格

c# - Unity 覆盖 `StandardAssetsScripts` 的最佳方式

c# - 将字符串列表放入 NSUserDefaults 对象