In C#, the compiler will pick the right method depending on the declared type of the variable, not on the actual type stored in it.
Note, the code below declares W to be a class, and constructs an instance of it. If you make W an interface, and remove its declaration and construction, you'll get the same behavior for x and y as the program below, interface or class for W in this case does not matter.
Let me show you the difference:
using System;
namespace SO2851194
{
class W { }
class X : W { }
class Y : W { }
class Program
{
static void Main()
{
W w = new W();
X x = new X();
Y y = new Y();
doSomething(w);
doSomething(x);
doSomething(y);
}
static void doSomething(W w)
{
Console.Out.WriteLine("w");
}
static void doSomething(X x)
{
Console.Out.WriteLine("x");
}
}
}
Here I declare three variables, of type W, X, and Y, and call doSomething passing the three variables, one by one. The output of this program is:
w
x
w
As expected, the compiler will pick the method that has the best fitting parameter type, and in the case of the x variable, it has a method that can take an object of type X.
However, due to class inheritance, we can change the declaration of the variables, but keep the object types constructed, so changing the code like this:
W w = new W();
W x = new X(); // Notice, changed variable type to W
W y = new Y(); // but keep constructing X and Y
This now outputs:
w
w
w
So the fact that the x variable contained an object of type X didn't factor into it, the compiler picked the method from the variable type, not its contents.
In C# 4.0, you now have the dynamic type, so again changing the code to:
dynamic w = new W();
dynamic x = new X();
dynamic y = new Y();
again outputs:
w
x
w
as now the compiler defers picking any method at all until runtime, and at runtime, it sees that the variable named x actually contains an object of type X and then picks the method with the best fitting parameter type.