No asistí a PDC 2008, pero escuché algunas noticias de que C # 4.0 se anunció para admitir la covarianza y contravarianza genéricas. Es decir, List<string>se puede asignar a List<object>. ¿Cómo es posible?
En el libro C # in Depth de Jon Skeet , se explica por qué los genéricos de C # no admiten la covarianza y la contravarianza. Es principalmente para escribir código seguro. Ahora, C # 4.0 cambió para admitirlos. ¿Traería el caos?
¿Alguien sabe los detalles sobre C # 4.0 puede dar alguna explicación?
c#
c#-4.0
covariance
contravariance
generic-variance
Morgan Cheng
fuente
fuente

Respuestas:
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>comoList<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) oout(para covarianza). El ejemplo más obvio es elIEnumerable<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 unIEnumerable<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 unTparámetro. Sería bueno poder convertir sin problemas el uso de anAction<object>comoAction<string>: cualquier método que tome unobjectparámetro estará bien cuando se presente con unstring. 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!
fuente
List<Banana>comoIList<Fruit>" como dijo @ Ark-kun? Si es así, cómo es posible, aunque el parámetro de tipo de laIList<T>interfaz no está definido como covariante (noout T, sino simplementeT).No es que Jon no lo haya cubierto ya, pero aquí hay algunos enlaces a blogs y videos de Eric Lippert. Hace un buen trabajo al explicarlo con ejemplos.
https://blogs.msdn.microsoft.com/ericlippert/2007/10/16/covariance-and-contravariance-in-c-part-one/
Los videos:
https://www.youtube.com/watch?v=3MQDrKbzvqU
https://www.youtube.com/watch?v=XRIadQaBYlI
https://www.youtube.com/watch?v=St9d2EDZfrg
fuente