Sorry, but you are completely mistaken; this would go against the entire point of virtual methods. If someObject
is an A
then A.MyMethod
will be invoked. If someObject
is a B
then B.MyMethod
will be invoked. If someObject
is a BaseClass
and not an instance of a type derived from BaseClass
then BaseClass.MyMethod
will be invoked.
Let's use everyone's favorite example:
class Animal {
public virtual void Speak() {
Console.WriteLine("i can haz cheezburger?");
}
}
class Feeder {
public void Feed(Animal a) { b.Speak(); }
}
class Cat : Animal {
public override void Speak() { Console.WriteLine("Meow!"); }
}
class Dog : Animal {
public override void Speak() { Console.WriteLine("Woof!"); }
}
Then:
Animal a = new Animal();
Animal c = new Cat();
Animal d = new Dog();
Feeder f = new Feeder();
f.Feed(a);
f.Feed(c);
f.Feed(d);
This will print:
i can haz cheezburger?
Meow!
Woof!
Again, this is the entire point of virtual methods.
Further, we can go to the specification. From 10.6.3 (Virtual methods)
In a virtual method invocation, the run-time type of the instance for which that invocation takes place determines the actual method implementation to invoke.
(Bolding and italics in original.)
In precise terms, when a method named N
is invoked with an argument list A
on an instance with a compile-time type C
and a run-time type R
(where R
is either C
or a class derived from C
), the invocation is processed as follows:
• First, overload resolution is applied to C
, N
, and A
, to select a specific method M
from the set of methods declared in and inherited by C
. This is described in §7.5.5.1.
• Then, if M
is a non-virtual method, M
is invoked.
• Otherwise, M
is a virtual method, and the most derived implementation of M
with respect to R is invoked.
(Bolding not in original.)
Then, we need the definition of "most derived implementation of M
." This is a nice recursive definition:
The most derived implementation of a virtual method M
with respect to a class R
is determined as follows:
• If R
contains the introducing virtual declaration of M
, then this is the most derived implementation of M
.
• Otherwise, if R
contains an override of M
, then this is the most derived implementation of M
.
• Otherwise, the most derived implementation of M
with respect to R
is the same as the most derived implementation of M
with respect to the direct base class of R
.
Thus, in our example above with Cat : Animal
and Dog : Animal
, when the parameter a
to Feeder.Feed(Animal)
is an instance of Cat
then Cat.Speak
is the most derived implementation. This is why we will see "Meow!
" and not "i can haz cheezburger?
"