Как генерируется общая ковариация и контра-дисперсия в С# 4.0?

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

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

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

Ответ 1

Отклонение будет поддерживаться только безопасным способом - фактически, используя способности, которые CLR уже имеет. Поэтому примеры, которые я даю в книге по попытке использовать List<Banana> как List<Fruit> (или что бы это там было), по-прежнему не сработают, но некоторые другие сценарии будут.

Во-первых, он будет поддерживаться только для интерфейсов и делегатов.

Во-вторых, для этого требуется, чтобы автор интерфейса/делегата украшал параметры типа in (для контравариантности) или out (для ковариации). Наиболее очевидным примером является IEnumerable<T>, который только позволяет вам принимать значения "из" - это не позволяет добавлять новые. Это станет IEnumerable<out T>. Это не повредит безопасности типов вообще, но позволяет вернуть IEnumerable<string> из метода, объявленного для возврата IEnumerable<object>, например.

Контравариантность сложнее дать конкретные примеры использования интерфейсов, но это легко с делегатом. Рассмотрим Action<T> - который представляет только метод, который принимает параметр T. Было бы неплохо легко преобразовать Action<object> в качестве Action<string> - любой метод, который принимает параметр object, будет хорошим, если вместо него будет представлен string. Конечно, С# 2 уже имеет ковариацию и контравариантность делегатов в некоторой степени, но через фактическое преобразование из одного типа делегата в другой (создание нового экземпляра) - см. Примеры P141-144. С# 4 сделает это более общим, и (я полагаю) избежит создания нового экземпляра для преобразования. (Вместо этого это будет ссылочное преобразование.)

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