使用覆盖C#重载

时间:2012-06-01 13:59:15

标签: c# overloading override

我可以自己回答这个问题,但是我想知道人们对这个问题的看法。这是:

当我们同时重载和覆盖时,将调用哪个方法?我只考虑类型重载而不是arity重载和类型重载是相关的。

让我举个例子:

class AA {}
class BB : AA {}

class A {
    public virtual void methodA(AA anAA) { Console.Write("A:methodA(AA) called"); }
    public virtual void methodA(BB aBB) { Console.Write("A:methodA(BB) called"); }
}

class B : A {
    public override void methodA(AA anAA) { Console.Write("B:methodA(AA) called"); }
}

new B().methodA(new BB());     // Case 1
new B().methodA(new AA());     // Case 2
new B().methodA((AA)new BB()); // Case 3

你能说出案例1,2和3会发生什么吗?

我个人认为过载是邪恶的,并且没有一致的想法可以导致可预测的答案。这完全基于编译器+ vm中实现的约定。

编辑:如果您对过载是邪恶的原因有疑问,可以阅读Gilad Brach

中的博客文章

由于

3 个答案:

答案 0 :(得分:6)

不,这完全可以预测。首先解析方法签名 - 即首先确定重载。然后,调用最多重写方法。所以输出将是:

  • A:方法A(BB)名为
  • B:方法A(AA)称为
  • B:方法A(AA)称为

在后两种情况下将调用采用AA实例的方法,因为这是传入的引用的类型,并且它是被调用的B的版本。请注意,即使这样也会产生相同的结果:

A instance = new B();
instance.methodA((AA)new BB()); // Case 3

答案 1 :(得分:3)

当编译器确定调用哪个方法时,重写方法将从方法集中排除。请参阅member lookup算法。因此,当您在methodA类型上致电B时,会在methodA类型中设置名为B的成员,并构建其基本类型:

override B.methodA(AA)
virtual A.methodA(AA)
virtual A.methodA(BB)

然后将具有ovveride修饰符的成员从set中删除:

virtual A.methodA(AA)
virtual A.methodA(BB)

这组方法是查找的结果。之后应用overload resolution来定义要调用的成员。

    调用
  1. A.methodA(BB),因为它的参数与参数匹配。
  2. A.methodA(AA)将被选中,但它是虚方法,所以实际调用转到B.method(AA)
  3. 与选项2相同

答案 2 :(得分:0)

我认为结果将是这个

案例1:Console.Write(“A:方法A(BB)调用”);

案例2:Console.Write(“B:方法A(AA)调用”);

案例3:Console.Write(“B:方法A(AA)调用”);

在案例3中,它将看起来是它传递的类型,它是B