需要了解C#虚拟方法的以下代码

时间:2012-07-06 05:26:10

标签: c# .net inheritance virtual-method

这是一个显示虚拟方法的小代码。

class A
{
  public virtual void F() { Console.WriteLine("A.F"); }
}
class B: A
{
  public override void F() { Console.WriteLine("B.F"); }
}
class C: B
{
  new public virtual void F() { Console.WriteLine("C.F"); }
}
class D: C
{
  public override void F() { Console.WriteLine("D.F"); }
}

class Test
{
  static void Main() 
  {
    D d = new D();
    A a = d;
    B b = d;        

    a.F();
    b.F();        
 }
}

此代码正在打印以下输出:

B.F
B.F

我无法理解为什么a.F()会打印B.F?

我认为它会打印DF,因为B类会覆盖A类的F(),然后使用“new”关键字将此方法隐藏在C类中,然后再次在D类中重写。所以最终DF保持不变

但它没有这样做。你能解释为什么要打印B.F?

4 个答案:

答案 0 :(得分:5)

A a = d;
a.F();

它会发现F()如下。

  1. 首先在class A
  2. 然后在class B
  3. 然后在class C
  4. 然后在class D
  5. 现在F()A中会找到B。因此将调用B.F()。在class C中,F()是不同的(因为它是新的实现,不会从A / B覆盖)。所以在第3步中,将找不到c.F()。在D类中,它会覆盖由C创建的新函数,因此也无法找到它。

    由于新的关键字,结果代码如下(关于虚拟覆盖)

        class A
        {
            public virtual void F() { Console.WriteLine("A.F"); }
        }
        class B: A
        {
            public override void F() { Console.WriteLine("B.F"); }
        }
        class C: B
        {
            public virtual void F1() { Console.WriteLine("C.F"); }
        }
        class D: C
        {
            public override void F1() { Console.WriteLine("D.F"); }
        }
    

答案 1 :(得分:2)

与允许多态的方法覆盖不同,使用new关键字隐藏方法只是命名问题(请注意,使用new只会删除隐藏某些内容的警告。)< / p>

在课程C中,当您声明:

new public virtual void F() { ... }

在这里,您要定义一个与超类F()无关的全新方法,该方法恰好具有相同的名称。

F的实例分配给AB类型的变量时,使用这些变量调用F()指向超类定义的方法。

想象一下,如果你没有调用C的方法F(),而是调用G()之类的方法。以下代码无法编译:

a.G();
b.G();

由于变量静态类型为AB,编译器无法看到新声明的方法。在您的示例中,情况也是如此,除了超类恰好调用名为F()的原始方法。

答案 2 :(得分:1)

A.F被B.F覆盖。因此,当A.F被调用时,它将执行B.F.B.F''连接'到'A.F'。

现在C.F用新关键字隐藏B.F. C.F与B.F / A.F无关。当你创建C,并调用F()时,它将执行C.F.如果将C转换为A或B类型,并调用F,它将执行B.F,因为B.F和A.F已连接。

D.F被C.F.覆盖。他们是连接的。当调用C.F或D.F时,它将执行D.F.现在,当您将对象D转换为A或B并调用F()时,它将调用B.F。

希望这有助于使其更清晰。

答案 3 :(得分:0)

正如其他人已经指出的那样,C中的new关键字隐藏了F的重载,因此在C或D中找不到适合的F重载。

如果您需要有关C#找到正确过载的更多详细信息,请阅读 那两个:

Jon Skeet: C# in Depth, chapter Overloading

Visual Studio 2010: Breaking changes, here: overload resolution