Ahora, para el ojo no entrenado, covarianza parece ser el mismo que upcasting, salvo que se refiere el casting de colecciones . (Y de una declaración similar se puede hacer con respecto a la contravarianza y downcasting).
¿Es realmente así de simple?
Covarianza no se trata de upcasting, aunque puedo ver por qué cree que está relacionado.
Covarianza es sobre la siguiente idea muy simple. Supongamos que tiene una variable derivedSequence
del tipo IEnumerable<Derived>
. Supongamos que tiene una variable baseSequence
del tipo IEnumerable<Base>
. Aquí, Derived
deriva de Base
. Entonces, 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 se upcasting. No es el caso que IEnumerable<Derived>
deriva 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 del tipo Base
se puedan asignar desde los objetos del tipo Derived
, y dado que IEnumerable<T>
es covariante en su parámetro, los objetos del tipo IEnumerable<Derived>
se pueden asignar a variables del tipo IEnumerable<Base>
.
Por supuesto, todavía no he explicado qué es la covarianza. En general, la covarianza tiene que ver con la siguiente idea simple. Digamos que usted tiene un mapeo F
de tipos de tipos (voy a denotar este mapeo por F<T>
; dado un tipo T
su imagen bajo el mapeo F
es F<T>
.) Digamos que este mapeo tiene la siguiente propiedad muy especial:
si X
es la asignación compatible con Y
, entonces F<X>
es la asignación compatible con F<Y>
también.
En este caso, decimos que F
es covariante en su parámetro T
. (Aquí, al decir que "A
es la asignación compatible con B
" donde A
y B
son los tipos de referencia significa que los casos 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.
La respuesta de Jason es bastante acertada. Para una explicación más detallada de la diferencia entre la covarianza y la compatibilidad de asignación, vea mi artículo sobre el tema. http://blogs.msdn.com/b/ericlippert/archive/2009/11/30/what-s-the-difference-between-covariance-and-assignment-compatibility.aspx Usted no está solo; Mucha gente confunde a estos dos. –
@Eric Lippert: Saludos. Si hubiera leído ese artículo antes, ¡es posible que nunca lo haya publicado! Me alegro de haberlo hecho. En verdad, me sorprendió que no haya una pregunta similar como esta en SO. –