I understand that non-virtual methods are statically bound, which means, as far as I understand, that its known at compile-time itself as to which method will be invoked on which object. This decision is taken based on the static type of the object(s). What confuses me is interfaces (rather than class) and static binding.
Consider this code,
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
Demo code: http://ideone.com/JOVmi
I understand the Line 1
. The compiler can know that b.f()
will invoke B.f()
because it knows the static type of b
which is B
.
But how does the compiler decide at compile-time itself that ia.f()
will call A.f()
? What is the static type of object ia
? Is it not IA
? But then that is an interface, and doesn't have any definition of f()
. Then how come it works?
To make the case more puzzling, lets consider this static
method:
static void g(IA ia)
{
ia.f(); //What will it call? There can be too many classes implementing IA!
}
As the comment says, there can be too many classes that implement the interface IA
, then how can the compile statically decide which method ia.f()
would call? I mean, say if I've a class defined as:
public class C : A, IA
{
public new void f() { Console.WriteLine("C.f()"); }
}
As you see, C
, unlike B
, implements IA
in addition to deriving from A
. That means, we've a different behavior here:
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()
Demo code : http://ideone.com/awCor
How would I understand all these variations, especially how interfaces and static binding together work?
And few more (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()
Please help me understanding all these, and how static binding is done by the C# compiler.