Дисперсия будет поддерживаться только безопасным способом - фактически с использованием способностей, которые уже есть у CLR. Так что примеры, которые я привожу в книге, пытаясь использовать List<Banana>
как List<Fruit>
(или что бы то ни было), все равно не сработают - но некоторые другие сценарии сработают.
Во-первых, он будет поддерживаться только для интерфейсов и делегатов.
Во-вторых, автор интерфейса / делегата требует, чтобы параметры типа были декорированы как in
(для контравариантности) или out
(для ковариации). Самый очевидный пример - IEnumerable<T>
, который позволяет только извлекать из него значения, но не позволяет добавлять новые. Это станет IEnumerable<out T>
. Это совсем не вредит безопасности типов, но позволяет вам вернуть IEnumerable<string>
из метода, объявленного для возврата IEnumerable<object>
, например.
Contravariance труднее привести конкретные примеры использования интерфейсов, но это легко с делегатом. Рассмотрим Action<T>
- это просто представляет метод, который принимает параметр T
. Было бы неплохо иметь возможность плавного преобразования, используя Action<object>
как Action<string>
- любой метод, который принимает параметр object
, будет в порядке, если вместо него будет представлен string
. Конечно, C # 2 уже имеет ковариацию и контравариантность делегатов в некоторой степени, но посредством фактического преобразования из одного типа делегата в другой (создание нового экземпляра) - см. P141-144 для примеров. C # 4 сделает это более общим, и (я полагаю) избежит создания нового экземпляра для преобразования. (Вместо этого это будет ссылочное преобразование.)
Надеюсь, это немного прояснит ситуацию - пожалуйста, дайте мне знать, если это не имеет смысла!