如何在virtual \ override中了解大多数派生实现

时间:2017-03-19 06:03:24

标签: c#

我无法弄清楚方法调用的确切原因,如果在多级继承的情况下有多个虚拟和覆盖,如何知道将调用哪个方法?

 public class A
    {
        public virtual void f1()
        {
            Console.WriteLine("A");
        }
    }

    public class B:A
    {
        public override void f1()
        {
            Console.WriteLine("B");
        }
    }

    public class C:B
    {
        public override void f1()
        {
            Console.WriteLine("C");
        }
    }

    public class D:C
    {
        public virtual void f1()
        {
            Console.WriteLine("D");
        }
    }

    public class E : D
    {
        public override void f1()
        {
            Console.WriteLine("E");
        }
    }


A aobj = new D(); 
aobj.f1();
//why output is "C" here

A aobj = new E();
aobj.f1();
//why output is again "C" and not "E"

我很困惑,需要其他人的帮助才能理解,编译器如何决定调用哪个函数?

2 个答案:

答案 0 :(得分:2)

在您的示例中,virtual关键字用于D.f1(),而不是override。由于基本方法D.f1()已经是虚拟的,因此无需将virtual标记为A.f1()

我不确定您是否注意到您当前的代码会引发CS0114警告:

CS0114: 'D.f1()' hides inherited member 'C.f1()'. 
To make the current member override that implementation, add the override keyword. 
Otherwise add the new keyword. 

class D更改为以下内容可以解决问题:

public class D:C
{
    public override void f1()    // Notice use of 'override' instead of 'virtual' 
    {
        Console.WriteLine("D");
    }
}

通过上述更改,将返回预期输出:

D
E

看看这两个问题,讨论一个非常类似的问题:

编辑:行为背后的基本原理

aobjclass A的一个实例。因此,从基类A向上工作以识别调用哪个版本的f1()最高覆盖方法C.f1()因此将被调用。使用virtual在D类中打破了覆盖的层次结构,因此在使用D.f1()的实例时不会调用E.f1()class A

答案 1 :(得分:0)

在你的D类中,你再次使用虚拟,你需要使用覆盖,它隐藏了c.F1()的继承

public class D:C
{
    public virtual void f1()
    {
        Console.WriteLine("D");
    }
}