Вариативность будет поддерживаться только безопасным способом - фактически, с использованием возможностей, которые уже есть в среде 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
. Конечно, в C # 2 уже есть ковариация и контравариантность делегатов в некоторой степени, но через фактическое преобразование из одного типа делегата в другой (создание нового экземпляра) - см. P141-144 для примеров. C # 4 сделает это более универсальным и (я считаю) позволит избежать создания нового экземпляра для преобразования. (Вместо этого это будет ссылочное преобразование.)
Надеюсь, это немного проясняет ситуацию - пожалуйста, дайте мне знать, если это не имеет смысла!
person
Jon Skeet
schedule
29.10.2008