Ну, это конечно не будет поддерживаться в C # 4. Есть фундаментальная проблема:
List<Giraffe> giraffes = new List<Giraffe>();
giraffes.Add(new Giraffe());
List<Animal> animals = giraffes;
animals.Add(new Lion()); // Aargh!
Держите жирафов в безопасности: просто скажите "нет" небезопасной дисперсии.
Версия массива работает, потому что массивы do поддерживают дисперсию ссылочного типа с проверкой времени выполнения. Суть обобщения заключается в обеспечении безопасности времени компиляции .
В C # 4 будет поддерживаться safe универсальная дисперсия, но только для интерфейсов и делегатов. Таким образом, вы сможете сделать:
Func<string> stringFactory = () => "always return this string";
Func<object> objectFactory = stringFactory; // Safe, allowed in C# 4
Func<out T>
является ковариантным в 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, вам нужно поддерживать один список, или вы были бы рады создать новый список? Если это приемлемо, List<T>.ConvertAll
ваш друг.