Разрешение перегрузки виртуальных методов

Рассмотрим код

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 и вызываю Add с параметрами типа int, то почему он вызывает метод Add с параметрами float

Derived obj =new Derived()
obj.Add(3,5)

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

Почему он не вызывает более специфический метод?

Ответ 1

Это по дизайну. В разделе 7.5.3 спецификации языка С# указано:

Например, набор кандидатов для вызова метода не включает переопределенные методы (§7.4), а методы в базовом классе не являются кандидатами, если применим какой-либо метод в производном классе (§7.6.5.1).

Другими словами, поскольку ваш класс Derived имеет непереопределенный метод Add, метод Add в классе Base (и его переопределенная версия в Derived) больше не является кандидатом на перегрузку разрешение.

Даже если Base.Add(int,int) будет лучшим совпадением, существование Derived.Add(float,float) означает, что метод базового класса даже не рассматривается компилятором.

Эрик Липперт обсуждает некоторые причины этого проекта в этом сообщении в блоге.

Ответ 2

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

при выборе перегрузки, если есть какие-либо совместимые методы, объявленные в производном классе, все сигнатуры, объявленные в базовом классе, игнорируются - даже если они переопределены в одном и том же производном классе!