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?"