Дисперсия не работает с делегатами со ссылочными типами - PullRequest
2 голосов
/ 01 октября 2010

а) Компилирует

        Func<string, bool> f1 = (Func<object, bool>)null;

б) Не

        Func<int, bool> f2 = (Func<object, bool>)null;

Почему типы значений здесь особенные? Нарушается ли контравариантность с типами значений?

1 Ответ

6 голосов
/ 01 октября 2010

Общая дисперсия работает только со ссылочными типами, да.(Это так, что CLR знает, что все по-прежнему просто ссылка, поэтому код JITted остается тем же ... биты, включенные в ссылку, одинаковы для любого типа, о котором вы говорите, тогда как int рассматривается как *Для 1002 * требуется преобразование в бокс. По сути, вы можете сохранить репрезентативную идентичность со ссылочными типами).

Из спецификации C # 4, раздел 13.1.3.2:

Тип T<A1, …, An> может быть преобразован в тип дисперсии T<B1, …, Bn>, если T является интерфейсом или типом делегата, объявленным с параметрами типа варианта T<X1, …, Xn>, и для каждого параметра типа варианта Xi выполняется одно из следующих значений:

  • Xi является ковариантным и существует неявное обращение или преобразование идентичности из Ai в Bi
  • Xi является контравариантным и существует неявное обращение или преобразование идентичности из Bi в Ai
  • Xiявляется инвариантным, и существует преобразование идентичности из Ai в Bi

Это «неявное ссылочное преобразование», а не просто «ябит «явное преобразование», который является проблемой для типов значений.

Для значительно более подробно об общей дисперсии см. серию блогов Эрика Липперта на тему .

...