Дисперсия не работает с делегатами со ссылочными типами

2

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

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

b) Не

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

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

Теги:
c#-4.0

1 ответ

6
Лучший ответ

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

Из спецификации С# 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

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

Более подробно об общей дисперсии см. в разделе Эрике Липперт в блоге.

  • 0
    THX, у меня было ощущение, что ответ «из-за спецификации», но очень разочаровывает, что типы значений не приглашаются на вечеринку.
  • 3
    @ Андрей: «из-за спецификации» подразумевает, что решение было произвольным, но это не так. Джон объясняет, почему нет: потому что int и object не являются совместимыми типами. Функция, которая возвращает int, не может использоваться как функция, которая возвращает объект, потому что функция, которая возвращает int, записывает 32-разрядное целое число в возвращаемое хранилище, а функция, которая возвращает объект, записывает, скажем, 64-битный указатель на выделенный в куче объект в обратном хранилище. Требования к размеру хранилища даже не одинаковы, поэтому типы просто несовместимы.
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню