Варіантність буде підтримуватися лише безпечним способом - фактично, використовуючи здібності, які 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 зробить це більш загальним, і (я вважаю) уникне створення нового екземпляра для конверсії. (Натомість це буде конвертація посилань.)
Сподіваюсь, це трохи вияснить це - будь ласка, повідомте мене, якщо це не має сенсу!