据我所知,非虚方法是静态绑定,这就意味着,就我所知,它在编译时本身已知哪个方法会被调用在哪个对象上。该决定基于对象类型的静态。令我困惑的是接口(而不是类)和静态绑定。C#中的非虚方法,静态绑定和接口#
考虑以下代码,
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
我明白Line 1
。编译器可以知道b.f()
将调用B.f()
因为它知道静态类型的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()
我怎么会理解所有这些变化,尤其是如何接口和静态绑定一起工作?
而且几个(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#编译器完成。
*静态绑定*在C#中的含义是什么呢? – Nawaz
这意味着该调用在编译时被解析为特定的方法(不管是否为接口方法),而不是简单地发出方法*名称*并让运行时图形*全部*出来。在这种情况下,该调用静态绑定到*特定*接口方法。编译器无法知道它将在接口场景中调用哪个对象类型。这同样适用于虚拟方法。编译器*可以确定最终方法调用的唯一场景是在非接口(类或结构)类型变量上调用非虚方法时。 – cdhowie