Почему я не могу использовать ковариацию с двумя типичными параметрами типа?

Рассмотрим следующий пример:

class Base {}

class Derived : Base {}

class Test1
{
    private List<Derived> m_X;

    public IEnumerable<Base> GetEnumerable()
    {
        return m_X;
    }
}

Это компилируется просто отлично, потому что IEnumerable<T> ковариантно в T

Однако, если я делаю то же самое, но теперь с дженериками:

class Test2<TBase, TDerived> where TDerived : TBase
{
    private List<TDerived> m_X;

    public IEnumerable<TBase> GetEnumerable()
    {
        return m_X;
    }
}

Я получаю ошибку компилятора

Невозможно преобразовать тип выражения 'System.Collection.Generic.List' для возврата типа 'System.Collection.Generic.IEnumerable'

Что я здесь делаю неправильно?

Ответ 1

Дело в том, что в первом случае Base известна как класс. Во втором случае параметр типа T может быть либо классом, либо структурой (так компилятор думает).

Решите случай, указав, что T - класс, и ошибка исчезнет:

class Test2<TBase, TDerived> where TDerived : class, TBase
{
    private List<TDerived> m_X;

    public IEnumerable<TBase> GetEnumerable()
    {
        return m_X;
    }
}

Таким образом, компилятор пытается показать нам, что TDerived может быть структурой (поскольку вы не указали ограничение class), и, как мы уже знаем, ковариация и контравариантность не работают с структурами.