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

7

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

你应该编辑问题标题以匹配问题。 - MarcinJuraszek
3个回答

7

使用 Override 和 New 关键字进行版本控制 (C# 编程指南)

如果在派生类中的方法前加上 new 关键字,该方法就被定义为与基类中的方法无关。

因此,来自 ABF 方法与来自 CD 的方法不是关联的,这就是你得到结果的原因。

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


1

它不应该...

A a = d;

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

另一方面,在这行代码中;

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

你正在声明使用 new 关键字,以避免使用基类中的 F() 方法。
如果你已经在 DC 类中重写了 F() 方法,所有实例将调用在 D 类中声明的 F() 方法。

0

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

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

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

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

但是所有调用实例的运行时类型都是D,这意味着在D中实现的F()将被调用。 - Garrett Biermann
直到方法F()被覆盖才是正确的。如果你使用new关键词,它将被处理为一个新的方法,而不是被覆盖的。 - Fendy
明白了!因为在运行时,调用者类型最接近的实现是B中的F(),对于a.F();而在C中的F(),对于c.F();d.F()被调用。 - Garrett Biermann
True。只需将c.F()视为新方法而不是继承的方法。 - Fendy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接