Bueno, esto ciertamente no se apoya en C# 4. Hay un problema fundamental:
List<Giraffe> giraffes = new List<Giraffe>();
giraffes.Add(new Giraffe());
List<Animal> animals = giraffes;
animals.Add(new Lion()); // Aargh!
Mantener jirafas segura: decir no a la varianza inseguro.
La versión de matriz funciona porque las matrices hacen varianza de tipo de referencia de soporte, con comprobación del tiempo de ejecución. El objetivo de los genéricos es proporcionar tiempo de compilación tipo de seguridad.
En C# 4 habrá compatibilidad con varianza genérica segura, pero solo para interfaces y delegados. Por lo que será capaz de hacer:
Func<string> stringFactory =() => "always return this string";
Func<object> objectFactory = stringFactory; // Safe, allowed in C# 4
Func<out T>
es covariante en T
porque T
se utiliza sólo en una posición de salida. Compare eso con Action<in T>
que es contravariant en T
porque T
sólo se utiliza en una posición de entrada allí, haciendo de este seguro:
Action<object> objectAction = x => Console.WriteLine(x.GetHashCode());
Action<string> stringAction = objectAction; // Safe, allowed in C# 4
IEnumerable<out T>
es covariante, así, haciendo de esta correcto en C# 4, como se ha señalado por otros:
IEnumerable<Animal> animals = new List<Giraffe>();
// Can't add a Lion to animals, as `IEnumerable<out T>` is a read-only interface.
en términos de trabajar alrededor de este en su situación en C# 2, se necesitan para mantener una lista, o le gustaría ser feliz la creación de una nueva lista? Si eso es aceptable, List<T>.ConvertAll
es tu amigo.
+1 solo para agregar a la respuesta de Jon (no es que necesite ayuda), siguiendo el ejemplo 'Func' al 'Func
Gracias por señalar el problema de seguridad del tipo. Eso es realmente útil. – AndiDog
¿Qué pasa con 'animals.Add (new Lion()); // ¡Aargh! '? Si puedes lanzar un "León" y usarlo como un "Animal", y si estás utilizando todos los elementos en "animales" como "Animal", ¿cuál es el problema? – Jeff