Полиморфные методы не работают на C # 4 - PullRequest
7 голосов
/ 15 ноября 2011

Я просто наткнулся на очень интересную проблему. Дать следующий код:

using System;

class Program
{
    class A { }
    class B : A { }

    private static void MyMethod(A a) /* first method */
    {
        Console.WriteLine("A"); ;
    }

    private static void MyMethod(B b) /* second method */
    {
        Console.WriteLine("B");
    }

    static void Main(string[] args)
    {
        var a = new A();
        // Call first method
        MyMethod(a);

        A b = new B();
        // Should call the second method
        MyMethod(b);

        Console.ReadLine();
    }
}

Я ожидаю, что будет вызван второй метод, потому что тип переменной во время выполнения - B. Есть идеи, почему код вызывает первый метод вместо этого?

Спасибо, Тиби

Некоторые пояснения: полиморфизм означает несколько форм, которые не имеют ничего общего с тем, когда вы объявляете метод.

Метод перегрузки является формой полиморфизма, специального полиморфизма.

Способ полиморфизма обычно реализуется с использованием позднего связывания.

динамическое решение для этой проблемы.

Дело в том, что это не работает в C # (или Java), это проектное решение, которое я хотел бы понять, почему было принято, и ни один из ответов не отвечает на этот вопрос.

/ Тиби

Ответы [ 3 ]

14 голосов
/ 15 ноября 2011

Это не пример полиморфизма вообще. Полиморфизм начинает действовать, когда вы вызываете методы ON объекта, а не когда объект используется в качестве параметра. Это просто простой пример перегрузки метода.

Вы объявили b как тип A, поэтому компилятор будет ссылаться на перегрузку, которая использует тип A. Компоновщику все равно, что B является подклассом A, он просто выбирает перегрузку с ближайшей сигнатурой к объявленным типам (не фактическим типам) параметров, переданных в.

Если вы хотите принудительно использовать второй метод, приведите b к типу B при вызове метода.

MyMethod((B)b);
6 голосов
/ 15 ноября 2011

Перегрузка метода в C # по умолчанию определяется статически во время компиляции.Поскольку вы передаете статически типизированную переменную типа A, она будет статически связываться с методом с перегрузкой A.Используйте ключевое слово dynamic, чтобы получить желаемое поведение.

static void Main(string[] args)
{
    dynamic d = new A();
    // Call first method
    MyMethod(d);

    d = new B();
    // Call the second method
    MyMethod(d);

    Console.ReadLine();
}
0 голосов
/ 15 ноября 2011

Второй метод не вызывается, поскольку ссылка на саму b имеет тип A. Хотя b содержит ссылку на экземпляр B, это не фактический тип B, поэтому выбрана перегрузка, использующая ссылку A.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...