虚方法的重载解析

本文关键字:重载 方法 | 更新日期: 2023-09-27 18:03:14

考虑以下代码

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);
   }
}

如果我创建一个派生类的实例,并使用int类型的参数调用Add,为什么它调用带有float参数的Add方法

Derived obj =new Derived()
obj.Add(3,5)
// why this is calling 
Add(float a,float b)

为什么不调用更具体的方法?

虚方法的重载解析

这是设计。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在这篇博文中讨论了这种设计的一些原因。

http://www.yoda.arachsys.com/csharp/teasers-answers.html

选择重载时,如果在派生类中声明了任何兼容的方法,那么在基类中声明的所有签名都将被忽略——即使它们在同一个派生类中被重写!