Вариант и открытые генераторы IReadOnlyList

Я пытаюсь понять, почему конкретное поведение в отношении варианта и дженериков в С# не компилируется.

class Matrix<TLine> where TLine : ILine
{
    TLine[] _lines;

    IReadOnlyList<ILine> Lines { get { return _lines; } } //does not compile
    IReadOnlyList<TLine> Lines { get { return _lines; } } //compile
}

Я не понимаю, почему это не работает:

  • _lines, имеющий тип TLine[], реализует IReadOnlyList<TLine>
  • IReadOnlyList<out T> - это вариантный общий интерфейс, что, насколько я понимаю, означает, что все, что реализует IReadOnlyList<TLine>, можно использовать как IReadOnlyList<ILine>

Я чувствую, что это должно быть потому, что ограничение типа не учитывается, но я в этом сомневаюсь.

Ответы

Ответ 1

Вам просто нужно добавить ограничение class к TLine:

class Matrix<TLine> where TLine : class, ILine

Это гарантирует, что TLine является ссылочным типом, который затем позволяет использовать общую дисперсию. Отклонение работает только для ссылочных типов, так как CLR знает, что значение типа TLine может использоваться как значение типа ILine без какого-либо бокса или другого изменения в представлении.