这段代码块的输出对我来说没有意义

时间:2013-04-08 06:15:52

标签: c# virtual-functions

所有调用实例的运行时类型都是D,因此,F()的所有调用都应该是在D中声明的F()方法。

using System;
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;
      C c = d;
      a.F();
      b.F();
      c.F();
      d.F();
   }
}

输出是:

B.F
B.F
D.F
D.F

输出不应该是:

D.F
D.F
D.F
D.F

3 个答案:

答案 0 :(得分:7)

Versioning with the Override and New Keywords (C# Programming Guide)

  

如果派生类中的方法前面有new关键字,   该方法被定义为独立于基础中的方法   类。

所以来自FA的{​​{1}}方法与<{1}}和B连接不一致,这就是为什么你得到你得到的东西。

在运行时CLR查找应该使用的C方法实现,从类型开始,声明变量的类型实际上是。对于Dvirtual,它会在a.F()声明中停止,因为b.F()是一种不同的方法(因为B.F())。

答案 1 :(得分:1)

您在C:B类中使用new public virtual void F()。这意味着班级F()中的C和班级F()中的B是不同的方法。

因此,当您将C覆盖为课程D时,课程F()中的方法D将从课程C覆盖,而不是B

另一个明显的例子可能是这样的:

  C c = new C();
  B b = c;
  b.F();
  c.F();

答案 2 :(得分:1)

它不应该......

A a = d;

这意味着您正在创建类型为A的类。因为你明确地覆盖了类B中的相关方法; A使用B类中的方法。

另一方面,在这一行;

new public virtual void F() { Console.WriteLine("C.F"); }

您声明使用F()关键字不会使用new方法。

如果您覆盖了F()D类中的C方法,则所有实例都会调用F()类中声明的D方法。< / p>