c# polymorphism covariance contravariance variance

C#: ¿La varianza(covarianza/contravarianza) es otra palabra para polimorfismo?



polymorphism covariance (5)

Estoy tratando de entender el significado exacto de las palabras Covariance y Contravariance de varios artículos en línea y preguntas sobre StackOverflow, y por lo que puedo entender, es solo otra palabra para polimorfismo .

¿Estoy en lo correcto con la declaración anterior? ¿O lo he entendido mal?


Ciertamente está relacionado con el polimorfismo. Sin embargo, no diría que son solo "otra palabra" para el polimorfismo: se trata de situaciones muy específicas, en las que puedes tratar un tipo como si fuera otro de un determinado contexto .

Por ejemplo, con el polimorfismo normal puede tratar cualquier referencia a un Banana como referencia a una Fruit , pero eso no significa que pueda sustituirla cada vez que vea el tipo de Banana . Por ejemplo, una List<Banana> no puede tratarse como una List<Fruit> porque la list.Add(new Apple()) es válida para la List<Fruit> pero no para la List<Banana> .

La covarianza permite que un tipo "más grande" (menos específico) sea sustituido en una API donde el tipo original solo se usa en una posición de "salida" (por ejemplo, como un valor de retorno). La contradicción permite que un tipo "más pequeño" (más específico) sea sustituido en una API donde el tipo original solo se usa en una posición de "entrada".

Es difícil analizar todos los detalles en una sola publicación de SO (aunque espero que alguien más haga un mejor trabajo que este). Eric Lippert tiene una excelente serie de publicaciones en el blog al respecto.


Creo que es un tipo especial de polimorfismo, no otra palabra para eso. Es un polimorfismo en delegados en el que un delegado con un tipo de base de retorno puede aceptar el tipo de niño.


Encontré esta colección:

here

Covarianza y contradicción en C #, parte dos: Covarianza en matriz

Covarianza y contradicción en C #, tercera parte: varianza de la conversión del grupo de miembros

Covarianza y contradicción en C #, cuarta parte: varianza de delegado real

Covarianza y contravarianza en C #, parte cinco: funciones de orden más altas hieren mi cerebro

Covarianza y contradicción en C #, parte seis: varianza de la interfaz

Covarianza y contradicción en C # Parte siete: ¿Por qué necesitamos una sintaxis?

Covarianza y contradicción en C #, parte ocho: opciones de sintaxis

Covarianza y contradicción en C #, parte nueve: cambios de última hora

Covarianza y contravarianza en C #, parte diez: lidiar con la ambigüedad

Covarianza y contravarianza, parte once: hasta el infinito, pero no más allá


Gracias por todos los gritos, muchachos.

Las respuestas de Jon y Rasmus están bien, solo agregaría una nota técnica rápida.

Cuando se habla casualmente e informalmente, sí, las personas usan "covarianza" y "contravarianza" para referirse a un tipo específico de polimorfismo. Es decir, el tipo de polimorfismo en el que se trata una secuencia de arañas como si fuera una secuencia de animales.

Si tuviéramos que obtener todas las ciencias de la computación e intentáramos hacer definiciones más técnicas, entonces probablemente no diría que la covarianza y la contravarianza son "una especie de polimorfismo". Me acercaría a una definición más técnica como esta:

Primero, señalaría que hay dos tipos posibles de polimorfismo en C # de los que podría estar hablando, y es importante no confundirlos.

El primer tipo es tradicionalmente llamado "polimorfismo ad hoc", y ese es el polimorfismo donde tienes un método M (Animal x), y pasas arañas y jirafas y wallabies hacia él, y el método trata uniformemente sus argumentos pasados ​​de la misma manera. manera mediante el uso de los puntos en común garantizados por la clase base Animal.

El segundo tipo se denomina tradicionalmente "polimorfismo paramétrico" o "polimorfismo genérico". Esa es la capacidad de hacer un método genérico M<T>(T t) y luego tener un montón de código en el método que una vez más, trata el argumento de manera uniforme en base a las características comunes garantizadas por las restricciones en T.

Creo que estás hablando del primer tipo de polimorfismo. Pero mi punto es que podemos definir el polimorfismo como la capacidad de un lenguaje de programación para tratar diferentes cosas de manera uniforme en función de una característica común conocida. (Por ejemplo, un tipo base conocido o una interfaz implementada conocida).

La covarianza y la contravarianza es la capacidad de un lenguaje de programación para aprovechar las características comunes entre los tipos genéricos deducidos de las similitudes conocidas de los argumentos de tipo.


Puedes pensar en co y contravariancia como una forma avanzada de polimorfismo. No solo puedes usar una clase hija como si fuera su clase padre, con co y contravariancia, el polimorfismo se extiende a las clases que se relacionan con las clases polimórficas.

Imagina dos clases:

public class Pet { /*...*/ } public class Cat:Pet { /*...*/ }

El polimorfismo es poder usar un Cat como Pet :

void Feed(Pet pet) { /* ... */ } Cat cat = ... Feed(cat);

Co y contravariancia se usa para hablar sobre poder usar un ICollection<Cat> como ICollection<Pet> (covarianza):

void FeedAll(ICollection<Pet> pets) { /* ... */ } List<Cat> cats = ... FeedAll(cats);

o para usar una Action<Pet> como una Action<Cat> (contravarianza):

Action<Pet> GetFeeder() { /* ... */ } Action<Cat> feeder = GetFeeder();

Eric Lippert escribió una gran serie de blogs sobre el tema cuando diseñaron por primera vez la función. La primera parte está here .