繁体   English   中英

带有重写的C#重载

[英]C# overload with override

我肯定可以自己编写一个虚拟测试来回答这个问题,但我想知道人们对这个问题的看法。 这里是:

当我们同时具有重载和重载时,将调用哪个方法? 我只考虑Type重载而不考虑Arity重载,而当Type重载相关时。

让我举个例子:

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会发生什么吗?

我个人认为重载是邪恶的,没有一致的想法可以得出可预测的答案。 这完全基于在compile + vm中实现的约定。

编辑:如果您对为什么超载是邪恶有疑问,可以阅读Gilad Brach的博客文章。

谢谢

不,这是完全可以预见的。 首先解决方法签名-即首先确定重载 然后,最重写的方法被调用。 因此输出将是:

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

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

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

当编译器确定要调用哪个方法时,重写的方法将从方法集中排除。 请参阅成员查找算法。 因此,当您在类型B上调用methodA时,将构造类型B且名称为methodA的成员集,该成员集是其基本类型:

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

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

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

这组方法是查找的结果。 之后,应用重载解析来定义要调用的成员。

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

我认为结果将是这样

情况1:Console.Write(“ A:methodA(BB)被称为”);

情况2:Console.Write(“ B:methodA(AA)被称为”);

情况3:Console.Write(“ B:methodA(AA)被称为”);

在情况3中,它将看起来像是传递的类型,它是B

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM