c#6 bug?虚拟新方法奇怪行为

时间:2016-07-22 04:03:57

标签: c#

我有这段代码:

using System;

namespace Test
{
    class Program
    {
        static void Main(string[] args)
        {
            Foo foo = new Foo();
            Bar bar = new Bar();
            Baz baz = new Baz();
            Foo fooBar = new Bar();
            Foo fooBaz = new Baz();
            Bar barBaz = new Baz();

            foo.Test();
            bar.Test();
            baz.Test();
            fooBar.Test();
            fooBaz.Test();
            barBaz.Test();

            Console.ReadLine();
        }
    }

    internal class Foo
    {
        public virtual void Test()
        {
            Console.WriteLine("Foo");
        }
    }

    internal class Bar : Foo
    {
        public new virtual void Test()
        {
            Console.WriteLine("Bar");
        }
    }

    internal class Baz : Bar
    {
        public override void Test()
        {
            Console.WriteLine("Baz");
        }
    }
}

它输出了我:

Foo
Bar
Baz
Foo
Foo
Baz

但是,我认为应该是:

Foo
Bar
Baz
Foo
Baz
Baz

因为Baz压倒了这个方法。这里发生了什么? 我错过了什么吗?为什么fooBaz.Test()的输出是“Foo”而不是“Baz”?

2 个答案:

答案 0 :(得分:5)

Buz覆盖了该方法,这就是

的原因
Bar barBaz = new Baz();
barBaz.Test();

将打印Baz

但是Bar没有覆盖 - 它隐藏基本方法Test并使新方法成为虚拟。然后Baz将覆盖Bar中的新方法,而不是来自Foo的方法。 因此,如果您像这样引用它:Foo fooBaz = new Baz();fooBaz被视为Foo的实例,它不知道隐藏方法。

如果您将public new virtual void Test()更改为public override void Test(),则会生成您期望的输出。

另见这些主题:

答案 1 :(得分:2)

当您在Bar.Test上使用新关键字时,您说它与Foo.Test无关,只是它具有相同的名称。由于Baz继承自Bar,它会覆盖Bar.Test,但不会修改Foo.Test

当您致电fooBaz.Test时,它会查找未经修改的Foo.Test方法并打印" Foo"。

当您致电barBaz.Test时,它会查找覆盖Bar.Test方法并打印" Baz"。