Я понимаю, что не виртуальные методы статически связаны, что означает, насколько я понимаю, что во время компиляции известно, какой метод будет вызываться для какого объекта. Это решение принимается на основе статического типа объекта (ов). Что меня смущает, так это интерфейсы (а не class ) и статическое связывание.
Рассмотрим этот код,
public interface IA
{
void f();
}
public class A : IA
{
public void f() { Console.WriteLine("A.f()"); }
}
public class B : A
{
public new void f() { Console.WriteLine("B.f()"); }
}
B b = new B();
b.f(); //calls B.f() //Line 1
IA ia = b as IA;
ia.f(); //calls A.f() //Line 2
Демонстрационный код: http://ideone.com/JOVmi
Я понимаю Line 1
. Компилятор может знать, что b.f()
вызовет B.f()
, потому что он знает тип static b
, который равен B
.
Но как компилятор решает во время самой компиляции , что ia.f()
будет вызывать A.f()
? Что такое статический тип объекта ia
? Разве это не IA
? Но тогда это интерфейс, и он не имеет определения f()
. Тогда как же это работает?
Чтобы сделать случай более загадочным, давайте рассмотрим этот static
метод:
static void g(IA ia)
{
ia.f(); //What will it call? There can be too many classes implementing IA!
}
Как говорится в комментарии, может быть слишком много классов, реализующих интерфейс IA
, тогда как компилятор статически может решить, какой метод ia.f()
будет вызывать? Я имею в виду, скажем, если у меня есть класс, определенный как:
public class C : A, IA
{
public new void f() { Console.WriteLine("C.f()"); }
}
Как видите, C
, в отличие от B
, реализует IA
в дополнение к A
. Это означает, что у нас другое поведение здесь:
g(new B()); //inside g(): ia.f() calls A.f() as before!
g(new C()); //inside g(): ia.f() doesn't calls A.f(), rather it calls C.f()
Демонстрационный код: http://ideone.com/awCor
Как бы я понял все эти варианты, особенно как работают интерфейсы и статическое связывание?
И еще несколько ( ideone ):
C c = new C();
c.f(); //calls C.f()
IA ia = c as IA;
ia.f(); //calls C.f()
A a = c as A;
a.f(); //doesn't call C.f() - instead calls A.f()
IA iaa = a as IA;
iaa.f(); //calls C.f() - not A.f()
Пожалуйста, помогите мне понять все это и как статическое связывание выполняется компилятором C #.