虚方法的重载决策

12

考虑以下代码

public class Base
{
   public virtual int Add(int a,int b)
   {
      return a+b;
   }
}

public class Derived:Base
{
   public override int Add(int a,int b)
   {
      return a+b;
   }

   public int Add(float a,float b)
   {
      return (Int32)(a + b);
   }
}
如果我创建一个Derived类的实例,并使用int类型的参数调用Add方法,为什么它会调用带有float参数的Add方法?
Derived obj =new Derived()
obj.Add(3,5)

// why this is calling 
Add(float a,float b)

为什么它没有调用更具体的方法?


1
你怎么知道3和5是整数?尝试指定它们的类型,看看会发生什么。 - Ritch Melton
你能编译这个吗?你可能会遇到一些类型转换错误,比如从浮点数到整数? - Anuraj
5
无法编译,因为float类型无法隐式转换为int类型。你确定第二个Add方法返回的是int类型吗? - Brian Rasmussen
@Ritch,@Matthew..即使您添加类似于int a = 3; int b = 5; obj.Add(a, b);的内容也没有任何区别。 - Ashley John
也请阅读约翰·斯基特(John Skeet)的以下文章。</br> http://csharpindepth.com/Articles/General/Overloading.aspx - Zain Ali
2个回答

21
这是有意设计的。C#语言规范的第7.5.3节中指出:
“例如,方法调用的候选集不包括标记为override的方法(§7.4),如果派生类中的任何方法适用(§7.6.5.1),则基类中的方法也不是候选集中的候选项。”
换句话说,因为你的Derived类有一个未重写的Add方法,所以Base类中的Add方法(以及Derived中重写的版本)不再是重载解析的候选项。
即使Base.Add(int,int)更匹配,Derived.Add(float,float)的存在意味着编译器根本不考虑基类方法。
Eric Lippert在这篇博文中讨论了一些这种设计的原因。

+1个好答案。附带证明、解释和进一步阅读的链接。 - Matt
有没有办法在保持原始方法可见的情况下为虚拟方法添加重载呢? - supercat

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接