Хорошо, что это не будет поддерживаться на C # 4. Существует фундаментальная проблема:
List<Giraffe> giraffes = new List<Giraffe>();
giraffes.Add(new Giraffe());
List<Animal> animals = giraffes;
animals.Add(new Lion()); // Aargh!
Хранить жирафов в безопасности: просто скажите «нет» небезопасной дисперсии.
Массив версия работает, потому что массивы do поддерживают отклонение ссылочного типа с проверкой времени выполнения. Пункт дженериков состоит в том, чтобы обеспечить безопасность типа compile-time .
В C # 4 будет поддерживаться универсальная дисперсия safe , но только для интерфейсов и делегатов. Таким образом, вы сможете:
Func<string> stringFactory = () => "always return this string";
Func<object> objectFactory = stringFactory; // Safe, allowed in C# 4
Func<out T>
covariant в T
, потому что T
используется только в выходной позиции. Сравните это с Action<in T>
, который контравариантен в T
, потому что T
используется только там, где находится входное положение, делая это безопасным:
Action<object> objectAction = x => Console.WriteLine(x.GetHashCode());
Action<string> stringAction = objectAction; // Safe, allowed in C# 4
IEnumerable<out T>
также является ковариантным, делая это исправить в C # 4, как указано другими:
IEnumerable<Animal> animals = new List<Giraffe>();
// Can't add a Lion to animals, as `IEnumerable<out T>` is a read-only interface.
Что касается работы с этим в вашей ситуации на C # 2, вам нужно поддерживать список one или Вы были бы счастливы создать новый список? Если это приемлемо, List<T>.ConvertAll
является вашим другом.