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