Теперь, на мой неопытный взгляд, ковариация, похоже, такая же, как и апскейтинг, за исключением того, что она относится к кастингу коллекций. (И аналогичное утверждение может быть сделано в отношении контравариантности и понижения).
Неужели это так просто?
Ковариантность не связана с апскейтингом, хотя я понимаю, почему вы думаете, что это связано.
Ковариантность о следующей очень простой идее. Допустим, у вас есть переменная derivedSequence
типа IEnumerable<Derived>
. Допустим, у вас есть переменная baseSequence
типа IEnumerable<Base>
. Здесь Derived
происходит от Base
. Затем, с ковариацией, следующее является законным назначением, и происходит неявное преобразование ссылки:
baseSequence = derivedSequence;
Обратите внимание, что это не upcasting. Это не тот случай, когда IEnumerable<Derived>
происходит от IEnumerable<Base>
. Скорее, это ковариация, которая позволяет вам присвоить значение переменной derivedSequence
переменной baseSequence
. Идея состоит в том, что переменные типа Base
могут быть назначены из объектов типа Derived
, и поскольку IEnumerable<T>
является ковариантным по своему параметру, объекты типа IEnumerable<Derived>
могут быть назначены переменным типа IEnumerable<Base>
.
Конечно, я еще не объяснил, что такое ковариация. В общем, ковариация заключается в следующей простой идее. Допустим, у вас есть отображение F
от типов к типам (я обозначу это отображение как F<T>
; для типа T
его изображение под отображением F
равно F<T>
.) Предположим, что это отображение имеет следующее особенное свойство:
, если X
совместимо с присвоением с Y
, то F<X>
также совместимо с назначением с F<Y>
.
В этом случае мы говорим, что F
является ковариантным по своему параметру T
. (Здесь сказать, что «A
совместимо с присваиванием с B
», где A
и B
являются ссылочными типами, означает, что экземпляры B
могут храниться в переменных типа A
.)
В нашем случае, IEnumerable<T>
в C # 4.0, неявное ссылочное преобразование из экземпляров IEnumerable<Derived>
в IEnumerable<Base>
, если Derived
получено из Base
. Направление совместимости присваивания сохраняется, и поэтому мы говорим, что IEnumerable<T>
ковариантен в параметре типа.