В C # компилятор выберет правильный метод в зависимости от объявленного типа переменной, а не от фактического типа, хранящегося в ней.
Обратите внимание, код ниже объявляет W
как класс и создает его экземпляр. Если вы сделаете W
интерфейсом и удалите его объявление и конструкцию, вы получите то же поведение для x
и y
, что и в приведенной ниже программе, интерфейс или класс для W
в этом случае не имеет значения.
Позвольте мне показать вам разницу:
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");
}
}
}
Здесь я объявляю три переменные типа W
, X
и Y
и вызываю doSomething
, передавая три переменные, одну за другой. Выход этой программы:
w
x
w
Как и ожидалось, компилятор выберет метод с наиболее подходящим типом параметра, а в случае переменной x
он имеет метод, который может принимать объект типа X
.
Тем не менее, из-за наследования классов, мы можем изменить объявление переменных, но оставить типы объектов построенными, поэтому изменив код следующим образом:
W w = new W();
W x = new X(); // Notice, changed variable type to W
W y = new Y(); // but keep constructing X and Y
Теперь выводится:
w
w
w
Таким образом, тот факт, что переменная x
содержала объект типа X
, не учитывал его, компилятор выбрал метод из типа переменной, а не из ее содержимого.
В C # 4.0 теперь у вас есть тип dynamic
, поэтому снова измените код на:
dynamic w = new W();
dynamic x = new X();
dynamic y = new Y();
снова выводит:
w
x
w
, так как теперь компилятор откладывает выбор любого метода вообще до времени выполнения, а во время выполнения он видит, что переменная с именем x
на самом деле содержит объект типа X
, а затем выбирает метод с наилучшим типом параметра.