Проблема перегрузки метода C # с классом, производным от общего абстрактного класса

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

Я столкнулся с интересной проблемой с перегрузкой метода в производном классе, который определен в абстрактном классе. Вот пример кода:

public abstract class AbstractConverter
    where U : AbstractConvertible
    where T : AbstractConverter
{
    public abstract T Convert(U convertible);
}

public class DerivedConvertibleConverter : AbstractConverter
{
    public DerivedConvertibleConverter(DerivedConvertible convertible)
    {
        Convert(convertible);
    }

    public override DerivedConvertibleConverter Convert(DerivedConvertible convertible)
    {
        //This will not be called
        System.Console.WriteLine("Called the most derived method");
        return this;
    }

    public DerivedConvertibleConverter Convert(Convertible convertible)
    {
        System.Console.WriteLine("Called the least derived method");
        return this;
    }
}

public abstract class AbstractConvertible {}

public class Convertible : AbstractConvertible {}

public class DerivedConvertible : Convertible {}

В приведенном выше примере вызывается перегрузка Convert, которая не существует в абстрактном родительском элементе (и является менее производной). Я ожидал, что будет вызвана самая производная версия от родительского класса.

Пытаясь устранить эту проблему, я натолкнулся на интересное решение:

public abstract class AbstractConverter
    where U : AbstractConvertible
{
    public abstract AbstractConverter Convert(U convertible);
}

public class DerivedConvertibleConverter : AbstractConverter
{
    public DerivedConvertibleConverter(DerivedConvertible convertible)
    {
        Convert(convertible);
    }

    public override DerivedConvertibleConverter Convert(DerivedConvertible convertible)
    {
        System.Console.WriteLine("Called the most derived method");
        return this;
    }

    public DerivedConvertibleConverter Convert(Convertible convertible)
    {
        System.Console.WriteLine("Called the least derived method");
        return this;
    }
}

public abstract class AbstractConvertible {}

public class Convertible : AbstractConvertible {}

public class DerivedConvertible : Convertible {}

Когда аргумент производного типа удаляется из базового класса, самая производная версия Convert называется. Я не ожидал такой разницы, поскольку не ожидал, что интерфейс абстрактной версии Convert изменится. Однако я должен ошибаться. Может ли кто-нибудь объяснить, почему возникает эта разница? Заранее большое спасибо.

6
задан Community 23 May 2017 в 09:58
поделиться