La varianza solo se admitirá de manera segura ; de hecho, utilizando las habilidades que ya tiene el CLR. Entonces, los ejemplos que doy en el libro de tratar de usar a List<Banana>
como List<Fruit>
(o lo que sea) todavía no funcionarán, pero algunos otros escenarios sí lo harán.
En primer lugar, solo será compatible con interfaces y delegados.
En segundo lugar, requiere que el autor de la interfaz / delegado decore los parámetros de tipo como in
(para contravarianza) o out
(para covarianza). El ejemplo más obvio es el IEnumerable<T>
que sólo le permite quitarle valores, no le permite agregar valores nuevos. Eso se convertirá IEnumerable<out T>
. Eso no perjudica la seguridad de tipos en absoluto, pero le permite devolver un IEnumerable<string>
de un método declarado para devolver, IEnumerable<object>
por ejemplo.
La contravarianza es más difícil de dar ejemplos concretos para el uso de interfaces, pero es fácil con un delegado. Considere Action<T>
: eso solo representa un método que toma un T
parámetro. Sería bueno poder convertir sin problemas el uso de an Action<object>
como Action<string>
: cualquier método que tome un object
parámetro estará bien cuando se presente con un string
. Por supuesto, C # 2 ya tiene covarianza y contravarianza de delegados hasta cierto punto, pero a través de una conversión real de un tipo de delegado a otro (creando una nueva instancia); consulte P141-144 para ver ejemplos. C # 4 hará que esto sea más genérico y (creo) evitará crear una nueva instancia para la conversión. (En su lugar, será una conversión de referencia).
Espero que esto lo aclare un poco; ¡avíseme si no tiene sentido!