Ich spiele seit einiger Zeit mit der Entwicklung von C # für Windows und ASP.net MVC. In einigen Bereichen bin ich jedoch noch unklar. Ich versuche, den grundlegenden Unterschied zwischen und Leistungsproblemen bei der Verwendung und dem Austausch ähnlicher Arten von generischen Sammlungsschnittstellen zu verstehen .
Was ist der grundlegende Unterschied zwischen IEnumerable<T>
, ICollection<T>
, List<T>(Class)
?
Ich scheine sie zu verwenden und auszutauschen, ohne Probleme in meinen Anwendungen zu sehen. Gibt es auch ähnliche generische Sammlungen wie diese, die mit diesen drei ausgetauscht werden können?
c#
generics
interfaces
Pankaj Upadhyay
quelle
quelle
Antworten:
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 , 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:
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:
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.
quelle
IList
anstelleList
der Methodendeklaration verwenden sollten.List<>
bestimmte Funktionen benötigen , wie z.AddRange()
. DasIList<>
macht das nicht sichtbar.Schauen Sie sich die MSDN-Seiten für ICollection und IEnumerable an .
In sehr abstrakten Begriffen stelle ich mir diese Typen so vor.
Ein IEnumerable ist alles, was aufgezählt werden kann - das heißt, es wird wiederholt. Es bedeutet nicht unbedingt eine "Sammlung"; Ein IQueryable implementiert beispielsweise IEnumerable und ist keine Sammlung, sondern kann abgefragt werden, um Objekte zurückzugeben. Um IEnumerable zu implementieren, muss ein Objekt nur in der Lage sein, ein Objekt zurückzugeben, wenn es abgefragt wird. Ich könnte sagen, dass ich eine Aufzählung von Aufgaben habe, die ich heute erledigen werde (es ist keine Liste, weil ich sie nicht aufgeschrieben oder formuliert habe, aber ich könnte Ihnen sagen, was ich jetzt tun werde, und Wenn Sie 'und dann?' gefragt haben, kann ich Ihnen die folgende Aufgabe mitteilen.
Eine ICollection ist konkreter als eine IEnumerable. Ein wesentlicher Unterschied besteht darin, dass eine Sammlung weiß, wie viele Elemente sie enthält. Um herauszufinden, wie viele Elemente sich in einer Aufzählung befinden, durchlaufen Sie diese effektiv und zählen sie:
Eine Sammlung ist normalerweise etwas, das bereits weiß, wo sich alle Elemente befinden, und sie nicht suchen oder generieren muss, wenn Sie danach fragen. Es ist mehr ... konkret als eine Aufzählung.
Meiner Meinung nach ist der Unterschied zwischen einer Aufzählung und einer Sammlung viel größer als der Unterschied zwischen einer Sammlung und einer Liste. Tatsächlich fällt es mir schwer, an einen praktischen Unterschied zwischen einer Sammlung und einer Liste zu denken, aber ich glaube, dass List bessere Methoden für die Suche und Bestellung bietet.
Andere Arten der Sammlung umfassen
Queue
undStack
, sowieDictionary
.Die Namen dieser Typen sind sehr nützlich - Sie können sich eine Warteschlange und einen Stapel als ihre realen Gegenstücke vorstellen und die Unterschiede berücksichtigen, die Sie möglicherweise zu einer Liste haben.
quelle
List
ist eineICollection
, aber eineICollection
ist nicht immer einList
(Queue
,Stack
,Dictionary
, ...)Queue<int> queue = (Queue<int>)list;
wird einInvalidCastException
Wann werfenlist
ist keinQueue<int>
. Der Unterschied zwischen Warteschlange und Liste ist für diese Frage nicht relevant.IQueryable:
Die Abfrage wird erst ausgeführt, um die Elemente wirklich zu durchlaufen, möglicherweise durch Ausführen einer .ToList ()
IEnumerable:
Nur-Vorwärts-Liste der Elemente. Sie können nicht zu "Punkt 4" gelangen, ohne die Punkte 0-3 zu übergeben. schreibgeschützte Liste, die Sie nicht hinzufügen oder daraus entfernen können. Möglicherweise wird die verzögerte Ausführung weiterhin verwendet.
IList:
Der zufällige Zugriff auf die vollständige Liste vollständig im Speicher unterstützt das Hinzufügen und Entfernen
ICollection:
Ist zwischen IEnumerable und IList. Was "am besten" ist, hängt von Ihren Anforderungen ab. Normalerweise ist eine IEnumerable jedoch "gut genug", wenn Sie nur Elemente anzeigen möchten. Verwenden Sie zumindest immer die generische Variante.
quelle