a) Компилирует
Func<string, bool> f1 = (Func<object, bool>)null;
b) Не
Func<int, bool> f2 = (Func<object, bool>)null;
Почему здесь важны типы значений? Существует ли нарушение контравариантности со значениями типов?
Общая дисперсия работает только со ссылочными типами, да. (Это значит, что 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
Это "неявное ссылочное преобразование", а не только бит "неявного преобразования", что является проблемой для типов значений.
Более подробно об общей дисперсии см. в разделе Эрике Липперт в блоге.