List <T> ist eine Klasse und implementiert sowohl die ICollection <T> - als auch die IEnumerable <T> -Schnittstelle. Außerdem erweitert ICollection <T> die IEnumerable <T> -Schnittstelle. Sie sind nicht austauschbar, zumindest nicht unter allen Gesichtspunkten.
Wenn Sie über eine Liste <T> verfügen, wird garantiert, dass dieses Objekt Methoden und Eigenschaften implementiert, die von der Schnittstelle ICollection <T> und IEnumerable <T> implementiert werden müssen. Der Compiler weiß es und Sie dürfen sie implizit entweder in eine ICollection <T> oder eine IEnumerable <T> "down". Wenn Sie jedoch über eine ICollection <T> verfügen, müssen Sie in Ihrem Code zunächst explizit überprüfen, ob es sich um eine Liste <T> oder etwas anderes handelt, möglicherweise um ein Wörterbuch <T> (wobei T ein KeyValuePair ist ), bevor Sie es in das übertragen, was Sie möchten Verlangen.
Sie wissen, dass ICollection IEnumerable erweitert, sodass Sie es in eine IEnumerable umwandeln können. Wenn Sie jedoch nur eine IEnumerable haben, kann Ihnen nicht garantiert werden, dass es sich um eine Liste handelt. Es mag sein, aber es könnte etwas anderes sein. Sie sollten eine ungültige Besetzungsausnahme erwarten, wenn Sie beispielsweise versuchen, eine Liste <T> in ein Wörterbuch <T> umzuwandeln.
Sie sind also nicht "austauschbar".
Es gibt auch viele generische Schnittstellen. Sehen Sie sich an, was Sie im System.Collections.Generic- Namespace finden.
Bearbeiten: In Bezug auf Ihren Kommentar gibt es absolut keine Leistungseinbußen, wenn Sie List <T> oder eine der implementierten Schnittstellen verwenden. Sie müssen noch ein neues Objekt erstellen. Überprüfen Sie den folgenden Code:
List<T> list = new List<T>();
ICollection<T> myColl = list;
IEnumerable<T> myEnum = list;
list , myColl und myEnum zeigen alle auf dasselbe Objekt. Unabhängig davon, ob Sie es als Liste, ICollection oder IEnumerable deklarieren, muss das Programm weiterhin eine Liste erstellen. Ich hätte das schreiben können:
ICollection<T> myColl = new List<T>();
myColl ist zur Laufzeit noch eine Liste.
Dies ist jedoch der wichtigste Punkt. Um die Kopplung zu verringern und die Wartbarkeit zu erhöhen, sollten Sie Ihre Variablen und Methodenparameter immer mit dem kleinstmöglichen Nenner deklarieren, unabhängig davon, ob es sich um eine Schnittstelle, eine abstrakte oder eine konkrete Klasse handelt.
Stellen Sie sich vor, die "PerformOperation" -Methode muss nur Elemente auflisten, einige Arbeiten ausführen und beenden. In diesem Fall benötigen Sie nicht die hundert weiteren in Liste <T> verfügbaren Methoden, sondern nur die in IEnumerable <T verfügbaren >, daher sollte folgendes gelten:
public void PerformOperation(IEnumerable<T> myEnumeration) { ... }
Auf diese Weise wissen Sie und andere Entwickler, dass dieser Methode jedes Objekt einer Klasse zugewiesen werden kann, die die IEnumerable <T> -Schnittstelle implementiert. Es kann sich um eine Liste, ein Wörterbuch oder eine benutzerdefinierte Sammlungsklasse handeln, die ein anderer Entwickler geschrieben hat.
Wenn Sie im Gegenteil angeben, dass Sie explizit eine konkrete Liste <T> benötigen (und obwohl dies im wirklichen Leben selten der Fall ist, kann dies dennoch vorkommen), wissen Sie und andere Entwickler, dass es sich entweder um eine Liste oder eine andere konkrete Klasse handeln muss, die diese erbt aus der Liste.