Pregunta

No asistí a PDC 2008, pero escuché algunas noticias de que C # 4.0 se anunció para respaldar la covarianza genérica y la contra-varianza. Es decir, List < string > se puede asignar a List < object > . ¿Cómo podría ser eso?

En el libro de Jon Skeet C # en profundidad , se explica por qué C # genéricos no admite la covarianza y la contra-varianza. Es principalmente para escribir código seguro. Ahora, C # 4.0 cambió para admitirlos. ¿Traería caos?

¿Alguien sabe que los detalles sobre C # 4.0 pueden dar alguna explicación?

¿Fue útil?

Solución

La variación solo se admitirá de una manera segura , de hecho, utilizando las habilidades que ya tiene el CLR. Entonces, los ejemplos que doy en el libro de tratar de usar una List < Banana > como una List < Fruit > (o lo que sea) todavía no funcionan, pero algunos otros escenarios 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 IEnumerable < T > que solo te permite sacar valores "". - no te permite agregar nuevos. Eso se convertirá en IEnumerable < out T > . Eso no perjudica en absoluto la seguridad de tipos, 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 usar interfaces, pero es fácil con un delegado. Considere Action < T > , que solo representa un método que toma un parámetro T . Sería bueno poder convertir sin problemas usar una Action < object > como Action < string > , cualquier método que tome un objeto el parámetro estará bien cuando se presente con una cadena en su lugar. 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 cambio, será una conversión de referencia).

Espero que esto lo aclare un poco. ¡Avíseme si no tiene sentido!

Otros consejos

No es que Jon aún no lo haya cubierto, pero aquí hay algunos enlaces a blogs y videos de Eric Lippert. Él hace un buen trabajo explicándolo 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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top