This very simple example confuses me:
public class X {
public void XMethod(A a) {
Console.WriteLine(a.GetType());
Console.WriteLine("Got A");
}
public void XMethod(B b) {
Console.WriteLine(b.GetType());
Console.WriteLine("Got B");
}
}
public abstract class A {
public virtual void M(X x) {
Console.WriteLine(this.GetType());
x.XMethod(this);
}
}
public class B : A {
}
class Program {
static void Main(string[] args) {
X x = new X();
B b = new B();
b.M(x);
}
}
Output of this is
B
B
Got A
Everything up until 'Got A' is fine. I would expect that method X.XMethod(B)
would be called when I invoke method M
on instance of class B
.
What is going on here? Why is XMethod(A)
called, and not XMethod(B)
, when it is clear that type of provided argument is B
and not A
?
PS: I got same output in java for equivalent implementation.
There is only on
A.M
method. Not one forA
and one forB
.The IL is the same, in
A.M
, for all instances; at compile-time,A.M
only knowsthis
to beA
(orobject
), hence it resolves always toXMethod(A)
. This method resolution is in the IL generated at compile-time, and doesn't change for subclasses (indeed, the subclass could be in a separate assembly that the compiler doesn't even know about):To get the behaviour you want, you could use
dynamic
. Not saying you should, though.