Какова Общая Ковариация & amp; Противоречивость Реализовано в C # 4.0?

StackOverflow https://stackoverflow.com/questions/245607

Вопрос

Я не посещал 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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top