Какова Общая Ковариация & amp; Противоречивость Реализовано в C # 4.0?
-
05-07-2019 - |
Вопрос
Я не посещал PDC 2008, но я слышал некоторые новости о том, что C # 4.0 объявлен для поддержки универсальной ковариации и контр-дисперсии. То есть List < string >
можно назначить для List < object >
. Как это могло быть?
В книге Джона Скита C # in Depth объясняется, почему дженерики C # не поддерживают ковариацию и противоречивость. Это в основном для написания безопасного кода. Теперь C # 4.0 изменился, чтобы поддержать их. Принесет ли это хаос?
Кто-нибудь знает подробности о C # 4.0, может дать некоторые объяснения?
Решение
Дисперсия будет поддерживаться только безопасным способом - фактически используя возможности, которые уже есть в CLR. Таким образом, примеры, которые я привожу в книге о попытке использовать List < Banana >
в качестве List < Fruit >
(или что бы то ни было), все равно не будут работать - но будет несколько других сценариев.
Во-первых, он будет поддерживаться только для интерфейсов и делегатов.
Во-вторых, он требует, чтобы автор интерфейса / делегата декорировал параметры типа как in
(для контравариантности) или out
(для ковариации). Наиболее очевидный пример - это IEnumerable < T >
, который позволяет только брать значения " out " об этом - это не позволяет добавлять новые. Это станет IEnumerable < out T >
. Это совсем не вредит безопасности типов, но позволяет вам вернуть IEnumerable < string >
из метода, объявленного для возврата, например, IEnumerable < object >
.
Contravariance труднее привести конкретные примеры использования интерфейсов, но это легко с делегатом. Рассмотрим Action < T >
- он просто представляет метод, который принимает параметр T
. Было бы неплохо иметь возможность плавного преобразования, используя Action < object >
в качестве Action < string >
- любой метод, который принимает object
Параметр будет в порядке, если вместо этого он представлен string
. Конечно, C # 2 уже имеет ковариацию и контравариантность делегатов в некоторой степени, но посредством фактического преобразования из одного типа делегата в другой (создание нового экземпляра) - см. P141-144 для примеров. C # 4 сделает это более общим, и (я полагаю) избежит создания нового экземпляра для преобразования. (Это будет ссылочное преобразование.)
Надеюсь, это немного прояснит ситуацию - пожалуйста, дайте мне знать, если это не имеет смысла!
Другие советы
Не то чтобы Джон еще не рассказал об этом, но вот несколько ссылок на блоги и видео Эрика Липперта Он хорошо объясняет это на примерах.
https://blogs.msdn.microsoft.com/ericlippert/2007/10/16/covariance-and-contravariance-in-c-part-one/ р>
Видео:
https://www.youtube.com/watch?v=3MQDrKbzvqU р>