Ошибка преобразования типа C # несмотря на общее ограничение - PullRequest
3 голосов
/ 31 июля 2009

Почему, с общим ограничением на параметр типа 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>?

Ответы [ 3 ]

7 голосов
/ 31 июля 2009

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

Пожалуйста, смотрите C # 4.0: Ковариация и Контравариантность :

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

0 голосов
/ 31 июля 2009

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

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

0 голосов
/ 31 июля 2009

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

S.DoSecond((ICollection<A>) new List<T>());      // this call will be happy
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...