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?
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. –
Sehr offensichtlich jetzt, dass Sie es erwähnen - danke! – LeopardSkinPillBoxHat