The problem is that you mix things up too much.
Basically, here is what you did:
- You define a virtual method
f in the base class - You drop from this base class and create a new virtual
f method - You drop from the second class and redefine
f , this redefines one from the second class, and not from the base class.
So when you say:
Base1 b = new Derived2(); bf();
then you are always (in this case) going to call the base implementation of f , since the overridden f in Derived2 is another f method. The name is the same, but it is still a different method.
The reason for this is because the compiler will see that the f you are calling is the one that comes from the Base1 class, and therefore it will call that.
Since the class does not override Base1.f , the one you are calling.
In response to a question in a comment, strictly speaking, the class will have two virtual methods, both of which are called f.
One, however, is obscured by the new one introduced in Derived1.
Inside the class, you can choose to call:
public void MethodInDerived1() { f();
From the outside, however, you need to βchooseβ by casting.
In other words:
Derived1 d = new Derived1(); df();
You can also observe methods through reflection. If you execute the following code in LINQPad , you will see that there are two methods named f :
void Main() { typeof(Derived1).GetMethods().Dump(); } public class Base1 { public virtual void f() { Debug.WriteLine("Base1.f"); } } public class Derived1 : Base1 { public virtual new void f() { Debug.WriteLine("Derived1.f"); } } public class Derived2 : Derived1 { public override void f() { Debug.WriteLine("Derived2.f"); base.f(); } }
The output from this script is truncated (there is more information on the right):
