Ошибка преобразования типа C # несмотря на общее ограничение

StackOverflow https://stackoverflow.com/questions/1214531

Вопрос

Почему, с общим ограничением на параметр типа T класса P, равным " должно наследоваться от A " ;, первый вызов завершается успешно, но второй вызов завершается с ошибкой преобразования типа, подробно описанной в разделе комментарий:

abstract class A { }

static class S
{
    public static void DoFirst(A argument) { }
    public static void DoSecond(ICollection<A> argument) { }
}

static class P<T>
    where T : A, new()
{
    static void Do()
    {
        S.DoFirst(new T());             // this call is OK

        S.DoSecond(new List<T>());      // this call won't compile with:

        /* cannot convert from 'System.Collections.Generic.List<T>'
           to 'System.Collections.Generic.ICollection<A>' */
    }
}

Разве общее ограничение не должно гарантировать, что List<T> действительно действительно ICollection<A>?

Это было полезно?

Решение

Это пример отсутствия в C # ковариации для универсальных типов (C # поддерживает ковариацию массива). C # 4 добавит эту функцию в типы интерфейсов, а также обновит несколько типов интерфейсов BCL для ее поддержки.

См. C # 4.0: Ковариация и контрвариация :

  

В этой статье я & # 8217; попробую осветить одну   нововведений в C # 4.0. Один из   новые функции ковариации и   контравариантность параметров типа,   теперь поддерживается общими делегатами   и общие интерфейсы. Сначала позвольте & # 8217; s   посмотрите, что означают эти слова:)

Другие советы

Ограничение не влияет на проблему; проблема в том, что вы передаете List в параметре, который требует ICollection - C # не поддерживает ковариацию, поэтому вам нужно явно привести список к ICollection:

S.DoSecond((ICollection<A>) new List<T>());      // this call will be happy

Вы строго ввели параметр для DoSecond как тип ICollection < A > ;. Несмотря на то, что T имеет тип A, во время компиляции неявное преобразование между List & Lt; T & Gt; и ICollection < A > ;. Вам нужно будет либо создать список и привести его к ICollection & Lt; A & Gt; когда вы вызываете DoSecond или делаете DoSecond самим универсальным методом.

ПРИМЕЧАНИЕ. Этот тип неявного приведения должен поддерживаться в C # 4.0, что значительно улучшит совместимость / контравариантность по сравнению с тем, что предлагает C # 3.0.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top