..

Variance generickych typu

Definice. Necht B je typove kompatibilni s A, typicky pokud B dedi od A. Muzu udelat A a = new B(); Potom typ C<T> je

Trochu lidsky

Priklady:

string[] sa = new string[10];
object[] so = sa;  // ok --> covariant

oa[0] = "Hello";  // ok
oa[1] = 5;  // prelozi se, ale pri behu to spadne
class A {...}
class B : A {...}

var a = new List<A>();
a = new List<B>();  // error
var o = new List<object>();
o = a;  // error

Ale bylo by to fajn. Možná nás zachrání interface IList<T>. Umí věci typu Count a indexovat.

Generické interfacy lze explicitně označit za covariant / contravariant. Ale jen pro refereční typy!!!

interface I1<T> {...}   // invariant
interface I2<out T> {   // covariant
    public T m();
    public void m(T a);  // error
}
interface I3<in T> {    // contravariant
    public T m();   // error
    public void m(T a);
}
interface I4<out T1, T2, in T3, in T4> {...}

I<A, B, C:G, D:H> = I<A/E:A, B, C/G, D/H>

Z toho plyne, že IList<T> musí být invariantní, protože má nějakou indexovací metodu, který bude mít setter (in T) a getter (out T).

Takže je potřeba nějaký interface, který je jen readonly… proto existuje IReadOnlyList, takže do IReadOnlyList<object> můžu předat cokoliv co ho implementuje… pole a list referenčních typů.

K čemu je sakra contravariance?

Pozor, tohle neni IComparable! c# má interface IComparer, který umí comparovat.

interface IComparer<in T> {
    int compare(T i1, T, i2);
}

abstract class Animal { string Name; int weight; }
class Cat : Animal { int Fluffiness }
class Elephant : Animal { int TrunkLength }

class AnimalWeightComparer : IComparer<Animal> {...}
class CatFluffinessComparer : IComparer<Cat> {...}

static void OrganizeCatCompetition(Cat c1, Cat c2, IComparer<Cat> comparer) {...}

Protože IComparer je contravariant, tak do té soutěže můžu strčit AnimalWeightComparer a porovnávat kočky podle váhy. Sortu totiž můžu předat IComparer.