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

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 polymorphism .

¿Estoy en lo correcto con la statement anterior? ¿O lo he entendido mal?

    Ciertamente está relacionado con el polymorphism. Sin embargo, no diría que son solo “otra palabra” para el polymorphism: 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 polymorphism 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 no puede tratarse como una List porque la list.Add(new Apple()) es válida para la List pero no para la List .

    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.

    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 polymorphism. Es decir, el tipo de polymorphism 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 polymorphism”. Me acercaría a una definición más técnica como esta:

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

    El primer tipo es tradicionalmente llamado “polymorphism ad hoc”, y ese es el polymorphism 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 “polymorphism paramétrico” o “polymorphism genérico”. Esa es la capacidad de hacer un método genérico M(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 polymorphism. Pero mi punto es que podemos definir el polymorphism como la capacidad de un lenguaje de progtwigció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 progtwigción para aprovechar las características comunes entre los tipos generics deducidos de las similitudes conocidas de los argumentos de tipo.

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

    Imagina dos clases:

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

    El polymorphism 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 como ICollection (covarianza):

     void FeedAll(ICollection pets) { /* ... */ } List cats = ... FeedAll(cats); 

    o para usar una Action como una Action (contravarianza):

     Action GetFeeder() { /* ... */ } Action 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á aquí .

    Encontré esta colección:

    Covarianza y contradicción en C #, primera parte

    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 syntax?

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

    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á

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