所有调用实例的运行时类型都是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
答案 0 :(得分:7)
Versioning with the Override and New Keywords (C# Programming Guide)
如果派生类中的方法前面有new关键字, 该方法被定义为独立于基础中的方法 类。
所以来自F
和A
的{{1}}方法与<{1}}和B
的连接不一致,这就是为什么你得到你得到的东西。
在运行时CLR查找应该使用的C
方法实现,从类型开始,声明变量的类型实际上是。对于D
和virtual
,它会在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>