The saying on MSDN:
Both covariant and contravariant are terms that are able to use a smaller (less specific) type than the derived type that was originally specified, which refers to the ability to use a more derived (more specific) type than the original specified derived type----------(Note that The more specific type that can be used here is the ability to pass a relatively less specific argument to a specific type.Generic type parameters support covariance and contravariance, which provides greater flexibility in the allocation and use of generic types.Covariance, contravariance, and invariance are defined as follows when referencing a type system.These examples assume a name ofbase and a derived class named derived . enables you to use a type that is more generic (less derived) than the original specified type. ienumerable< Base> (ienumerable (of Base) in Visual Basic) to a variable of type ienumerable<derived>. " > You can assign ienumerable<derived> -type variables >ienumerable< Base> (for ienumerable (of Base) in Visual Basic.
ienumerable< Base> (ienumerable (of Base) in Visual Basic) to a variable of type ienumerable<derived>. " > > I feel that MSDN is a bit of a mouthful.
ienumerable< Base> (ienumerable (of Base) in Visual Basic) to a variable of type ienumerable<derived>. " > ienumerable< Base> (ienumerable (of Base) in Visual Basic) to a variable of type ienumerable<derived>. " > invert: contravariance, type parameter with in keyword.
In a nutshell, suppose there is a generic contravariant interface ido<in T> when there are two types A and b that can replace T, B can assign an instance of ido<a> to Ido<b> if it inherits to A; for example:
private void Button1_Click (object sender, EventArgs e) {ido<a> A = new dot<a>(); ido<b> B = new dot<b>(); Run Run = new run (); Run. Set<d>(a);} interface Ido<in t>{void do (T t);} Class A {}class b:a {}class d:b {}class c:a {}class e:c {}class dot<t>: ido<t >{public void do (T-t) {MessageBox.Show (T.gettype (). ToString ()); }}class run{public void set<t> (ido<t> it) where T:new() {it. Do (new T ());//returns the type of D MessageBox.Show (it). GetType (). ToString ());//Returns the interface type of a }}
Covariant: Covariance, type uses the Out keyword.
This is easier to understand relative to contravariance when there are two types A and b that can replace T when there is an interface ido<out t>, b if inheriting to A, you can assign an instance of ido<b> to Ido<a> Saying it's easier to understand is because the Richter replacement is familiar, this looks a bit like, but don't confuse, it's two different things, examples:
Interface Ido<out t> { T get(); } private void Button1_Click (object sender, EventArgs e) { ido<a> A = new dot<a>(); ido<b> B = new dot<b>(); Run Run = new run (); Set<a>(b);}
It is also important to note that the t using in is only used as an input parameter, not as a return value. Use out parameters can only be used as the return value, can not do input parameters.
I have written an essay that uses covariant features in implementation: Evolution from inheritance to role play.
. The inverse covariant in net