Как реализована общая ковариантность и контрастность в C # 4.0? - PullRequest
106 голосов
/ 29 октября 2008

Я не посещал PDC 2008, но слышал некоторые новости о том, что C # 4.0 объявлен для поддержки универсальной ковариации и контр-дисперсии. То есть List<string> может быть присвоено List<object>. Как это могло быть?

В книге Джона Скита C # в глубине объясняется, почему дженерики C # не поддерживают ковариацию и противоречие. Это в основном для написания безопасного кода. Теперь C # 4.0 изменился, чтобы поддержать их. Принесет ли это хаос?

Кто-нибудь знает подробности о C # 4.0, может дать некоторые объяснения?

Ответы [ 2 ]

154 голосов
/ 29 октября 2008

Дисперсия будет поддерживаться только безопасным способом - фактически с использованием способностей, которые уже есть у 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 сделает это более общим, и (я полагаю) избежит создания нового экземпляра для преобразования. (Вместо этого это будет ссылочное преобразование.)

Надеюсь, это немного прояснит ситуацию - пожалуйста, дайте мне знать, если это не имеет смысла!

5 голосов
/ 16 апреля 2010

Не то чтобы Джон еще не рассказал об этом, но вот несколько ссылок на блоги и видео от Эрика Липперта Он хорошо объясняет это примерами.

https://blogs.msdn.microsoft.com/ericlippert/2007/10/16/covariance-and-contravariance-in-c-part-one/

Видео:

https://www.youtube.com/watch?v=3MQDrKbzvqU

https://www.youtube.com/watch?v=XRIadQaBYlI

https://www.youtube.com/watch?v=St9d2EDZfrg

...