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

本文关键字:对我来说 有意义 输出 代码 | 更新日期: 2023-09-27 18:08:12

所有调用实例的运行时类型都是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

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

使用覆盖和新关键字进行版本控制(c#编程指南)

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

所以ABF方法与CD的方法没有连接,这就是为什么你得到了你得到的。

在运行时CLR查找virtual方法实现,应该从变量声明的类型开始使用,直到它真正的类型。对于a.F()b.F(),它在B.F()声明时停止,因为C.F()是不同的方法(因为new)。

不应该…

A a = d;

这意味着您正在创建一个类型为A的类。并且由于您显式重写了类B中的相关方法;A使用B类中的方法。

另一方面,在这一行;

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

通过使用new关键字,您声明您将不使用F()方法。

如果在DC类中重写了F()方法,那么所有实例都将调用D类中声明的F()方法。

您在C:B类中使用new public virtual void F()。说明C类中的F()B类中的F()是不同的方法。

因此,当您将C重写为D类时,D类中的F()方法将从C类重写,而不是从B类重写。

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

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