2016-09-20 1 views
0

Der Grund, warum List<T> nicht auf T kovariant, während IEnumerable<T>ist covariant auf T oft durch ein Beispiel, wie dies dargestellt ist.Allgemein Kovarianz Kompilierung Sicherheitsprüfungen

die folgenden Klassen Gegeben:

public class Fruit 
{ 
} 

public class Apple : Fruit 
{ 
} 

public class Banana : Fruit 
{ 
} 

Die folgende zulässig:

public void Permitted() 
{ 
    IEnumerable<Fruit> bananas = new List<Banana> 
    { 
     new Banana(), 
     new Banana(), 
     new Banana(), 
    }; 

    foreach (Fruit banana in bananas) 
    { 
     // This is all good, because a banana "is a" fruit and 
     // we can treat it as such. 
    } 
} 

Die folgende nicht erlaubt ist:

public void Disallowed() 
{ 
    // Compiler rejects this! 
    List<Fruit> bananas = new List<Banana> 
    { 
     new Banana(), 
     new Banana(), 
     new Banana(), 
    }; 

    // ...Otherwise we can add an apple to a list containing bananas 
    bananas.Add(new Apple()); 
} 

Aber wir dies noch erreichen kann, indem Sie folgende:

public void Loophole() 
{ 
    // Compiler is happy again 
    IEnumerable<Fruit> bananas = new List<Banana> 
    { 
     new Banana(), 
     new Banana(), 
     new Banana(), 
    }; 

    // ...And now we can add an apple to a list of bananas 
    bananas.ToList().Add(new Apple()); 
} 

Und natürlich können wir dies nur tun:

public void AlsoAllowed() 
{ 
    var fruit = new List<Fruit>(); 
    fruit.Add(new Apple()); 
    fruit.Add(new Banana()); 
} 

Das gemeinsame Argument für List<T> nicht covariant sein (laut meinem Verständnis) ist, dass so wir ein jedes beliebiges Basisobjekt hinzufügen würde es ermöglichen tun Sammlung, die abgeleitete Objekte enthält. Vielleicht ist dies eine zu starke Vereinfachung, aber machen die obigen Beispiele das nicht?

Antwort

4

Wenn Sie bananas.ToList().Add(new Apple()) tun, erstellt bananas.ToList() eine List<Fruit>. Dies ist ein Listentyp, der jede Art von Obst enthalten kann. Die Tatsache, dass new Apple() zu dieser Liste hinzugefügt werden kann, ist sinnvoll.

bananas hat den Typ List<Banana>, ein Listentyp, der nur Bananen enthalten kann. Es gibt keine Möglichkeit new Apple() zu dieser Liste hinzuzufügen, und Ihre Beispiele nicht fügen Sie new Apple() zu dieser Liste hinzu. Ihre Beispiele erstellen eine tolerantere Liste und fügen diese hinzu, belassen die ursprüngliche Liste jedoch unverändert.

+0

Nur um das hinzuzufügen, im zweiten Beispiel ist absolut nichts falsch daran, 'Apple's und' Banana's zu 'fruit' hinzuzufügen, die nicht nur als" List "eingegeben, sondern instanziiert werden. –

+0

Sehr offensichtlich jetzt, dass Sie es erwähnen - danke! – LeopardSkinPillBoxHat