Производный класс, используя неправильный метод - PullRequest
6 голосов
/ 28 марта 2012

Я упростил свой код до этого

 internal class Program
{
    private static void Main(string[] args)
    {
        Child d = new Child();
        int i = 100;
        d.AddToTotal(i);

        Console.ReadKey();
    }

    private class Parent
    {
        public virtual void AddToTotal(int x)
        {
            Console.WriteLine("Parent.AddToTotal(int)");
        }
    }

    private class Child : Parent
    {
        public override void AddToTotal(int number)
        {
            Console.WriteLine("Child.AddToTotal(int)");
        }

        public void AddToTotal(double currency)
        {
            Console.WriteLine("Child.AddToTotal(double)");
        }
    }
}

Проблема в том, что это вызывает

public void AddToTotal(double currency)

, хотя я вызываю его с помощью int, и он должен использовать

public override void AddToTotal(int number)

Использование родителя возвращает ожидаемый результат.

 Parent d = new Child();
 int i = 100;
 d.AddToTotal(i);

Обновление:

Спасибо @Jan и @azyberezovsky за указание на спецификацию ,Я добавил виртуальный пустой метод в базовый класс, чтобы обойти это сейчас.

Ответы [ 2 ]

8 голосов
/ 28 марта 2012

A поиск члена имени N в типе T обрабатывается следующим образом:

Сначала набор всех доступных членов с именем N, объявленных в T, и базовые типы Tпостроен Декларации, которые включают модификатор override , исключены из набора. Если ни один элемент с именем N не существует и не доступен, то поиск не дает совпадения, и следующеешаги не оцениваются.

Таким образом, при использовании переменной типа Child

Child d = new Child();
int i = 100;
d.AddToTotal(i);

метод public override void AddToTotal(int number) исключается из набора, и у нас остается только один метод с именем N.Int неявно преобразуется в double, поэтому ошибок не было.

1 голос
/ 28 марта 2012

Этот ответ на этот вопрос объясняет технические причины, по которым это происходит. Я включил здесь ответ для удобства, но все из-за tvanfosson .

См. Раздел Спецификации языка C # в Поиск членов и Разрешение перегрузки . Метод переопределения производного класса не является кандидатом из-за правил поиска членов и базы метод класса не является лучшим соответствием, основанным на разрешении перегрузки правила.

Раздел 7.3

Во-первых, набор всех доступных (раздел 3.5) членов с именем N объявлено в T и базовые типы (раздел 7.3.1) из T построен. Объявления, содержащие модификатор переопределения, исключаются из задавать. Если ни один член с именем N не существует и не доступен, то поиск не дает совпадений, и следующие шаги не оцениваются.

Раздел 7.4.2:

Каждый из этих контекстов определяет набор функций-кандидатов и список аргументов по-своему уникальным образом, как описано в подробно в разделах, перечисленных выше. Например, набор Кандидаты на вызов метода не включают помеченные методы переопределить (раздел 7.3), а методы в базовом классе не являются кандидатами если применим какой-либо метод в производном классе (раздел 7.5.5.1). (выделение мое)

...