c# casting covariance

c# - Diferencia entre covarianza y upcasting



covariance (6)

Ahora, para mi ojo no entrenado, la covarianza parece ser lo mismo que la upcasting, excepto que se refiere al lanzamiento de colecciones. (Y de una declaración similar se puede hacer con respecto a la contravarianza y downcasting).

¿Es así de simple?

La covarianza no se trata de upcasting, aunque puedo ver por qué piensas que está relacionado.

La covarianza se trata de la siguiente idea muy simple. Supongamos que tiene una variable derivedSequence de tipo IEnumerable<Derived> . Digamos que tiene una baseSequence variable de tipo IEnumerable<Base> . Aquí, Derived deriva de Base . Luego, con la covarianza, la siguiente es una asignación legal y se produce una conversión de referencia implícita:

baseSequence = derivedSequence;

Tenga en cuenta que esto no es upcasting. No es el caso que IEnumerable<Derived> derive de IEnumerable<Base> . Más bien, es la covarianza lo que le permite asignar el valor de la variable derivedSequence a la variable baseSequence . La idea es que las variables de tipo Base se puedan asignar desde objetos de tipo Derived , y dado que IEnumerable<T> es covariante en su parámetro, los objetos de tipo IEnumerable<Derived> se pueden asignar a variables de tipo IEnumerable<Base> .

Por supuesto, todavía no he explicado realmente qué es la covarianza. En general, la covarianza tiene que ver con la siguiente idea simple. Digamos que tiene un mapeo F de tipos a tipos (denotaré este mapeo por F<T> ; dado un tipo T su imagen bajo el mapeo F es F<T> .) Digamos que este mapeo tiene el siguiente muy propiedad especial:

si X es compatible con Y , entonces F<X> es compatible con F<Y> .

En este caso, decimos que F es covariante en su parámetro T (Aquí, decir que " A es asignación compatible con B ", donde A y B son tipos de referencia significa que las instancias de B se pueden almacenar en variables de tipo A ).

En nuestro caso, IEnumerable<T> en C # 4.0, una conversión de referencia implícita de instancias de IEnumerable<Derived> a IEnumerable<Base> si Derived se deriva de Base . La dirección de la compatibilidad de asignación se conserva, y es por eso que decimos que IEnumerable<T> es covariante en su parámetro de tipo.

¿Cuál es la diferencia entre covarianza y upcasting, o, más específicamente, por qué reciben diferentes nombres?

He visto el siguiente ejemplo denominado ''upcasting'':

string s = "hello"; object o = s; //upcast to ''string'' to ''object''

Mientras que, lo siguiente he visto llamado ''covarianza'':

string[] s = new string[100]; object[] o = s; IEnumerable<string> ies = new List<string>(); IEnumerable<object> ieo = ies;

Ahora, para mi ojo no entrenado, la covarianza parece ser lo mismo que la upcasting, excepto que se refiere al lanzamiento de colecciones. (Y de una declaración similar se puede hacer con respecto a la contravarianza y downcasting).

¿Es así de simple?


De lo que puedo deducir, la covarianza elimina la necesidad de downcasting explícito posterior a un upcast previo. Normalmente, si modifica un objeto, solo puede acceder a los métodos y atributos de tipo base, con la covarianza parece que puede implicar el downcast reemplazando los tipos derivados menores con más tipos derivados en la declaración de clase más derivada.



La razón por la que son conceptos diferentes es que, a diferencia de la difusión ascendente, la covarianza no siempre está permitida. Hubiera sido fácil para los diseñadores del sistema de tipos hacer que IList<Cat> se considerara como "derivado" de IList<Animal> , pero luego nos encontramos con problemas:

IList<Cat> cats = new List<Cat>(); IList<Animal> animals = cats; animals.Add(new Dog()); //Uh oh!

Si esto fuera permitido, ¡ahora nuestra lista de cats contendría un Dog !

Por el contrario, la IEnumerable<T> no tiene forma de agregar elementos, por lo que esto es perfectamente válido (en C # 4.0):

IList<Cat> cats = new List<Cat>(); IEnumerable<Animal> animals = cats; //There''s no way to add things to an IEnumerable<Animal>, so here we are ok


IEnumerable<string> no se deriva de IEnumerable<object> , por lo que el molde entre ellos no es upcasting. IEnumerable es covariante en su parámetro de tipo y la cadena se deriva de un objeto, por lo que se permite el lanzamiento.


Casting se refiere a cambiar el tipo estático de objetos y expresiones .

La varianza se refiere a la intercambiabilidad o equivalencia de tipos en ciertas situaciones (como parámetros, genéricos y tipos de devolución).