我有三个简单的课程:
class A { public virtual void Write() { Console.Write("A"); } } class B:A { public override void Write() { Console.Write("B"); } } class C : B { public new void Write() { Console.Write("C"); } }
A a = new A(); a.Write(); A b = new C(); b.Write(); C c = new C(); c.Write();
输出将是:ABC
我无法理解的是为什么这些代码产生B?:
A b = new C(); b.Write();
我认为它应该是C.但是,我测试了很多次,它总是B.
我知道A b = new C()会创建C的新对象类型.所以输出应该是C.或者在我们使用它而不进行转换时调用重写方法是特殊行为?
为什么会这样?因为我们没有使用任何对B类的引用.
解决方法
如果你使用((C)b).Write();
使用new关键字,您不会覆盖C的Write方法,而是创建仅为C定义的新方法.因此,对于C,您实际上有2个方法名为Write的方法.
A c = new C(); c.Write(); //Output "B",you're calling the overridden method ((C)c).Write(); //Output "C",you're calling the method defined on C //or (c as C).Write();
将c定义为C时会发生同样的情况:
C c = new C(); c.Write(); //Output "C" ((A)c).Write(); //Output "B"
在第一个示例中,您将调用在C上定义的新方法.在第二行中,您从A调用Write方法,由B重写,因此输出“B”.
编辑:(更多解释)
变量c是A类型,因此您的编译器知道“c是A的实例”,不知道它实际上是更多派生类型.当您调用方法Write on时,它将调用A上定义的方法(由B覆盖).你的基类A不知道你在C上定义的新方法(这就是新的方法,创建一个新方法),所以除非你把它转换为C让编译器知道c的实际派生类型,你的基类将被调用.