Normalerweise hängt Ihre Auswahl davon ab, auf welche Methoden Sie zugreifen müssen. Im Allgemeinen - IEnumerable<>
(MSDN: http://msdn.microsoft.com/en-us/library/system.collections.ienumerable.aspx ) für eine Liste von Objekten, die nur durchlaufen werden müssen ICollection<>
(MSDN: http: // msdn.microsoft.com/en-us/library/92t2ye13.aspx ) für eine Liste von Objekten, die durchlaufen und geändert werden müssen, List<>
für eine Liste von Objekten, die durchlaufen, geändert, sortiert usw. werden müssen (siehe hier) Für eine vollständige Liste: http://msdn.microsoft.com/en-us/library/6sh2ey19.aspx ).
Unter einem genaueren Gesichtspunkt spielt das verzögerte Laden eine Rolle bei der Auswahl des Typs. Standardmäßig werden Navigationseigenschaften in Entity Framework mit Änderungsverfolgung geliefert und sind Proxys. Damit die dynamische Proxy als Navigationseigenschaft geschaffen werden, der virtuelle Typ muss implementieren ICollection
.
Eine Navigationseigenschaft, die das "viele" Ende einer Beziehung darstellt, muss einen Typ zurückgeben, der ICollection implementiert, wobei T der Typ des Objekts am anderen Ende der Beziehung ist. - Anforderungen zum Erstellen von POCO Proxies MSDN
Weitere Informationen zum Definieren und Verwalten von Beziehungen MSDN
List
Also , sollte das viel besser sein, ja?List
viel zu verwenden. Obwohl es den größten Overhead hat, bietet es die meisten Funktionen.private IEnumerable<int> _integers = new List<int> { 1, 2, 3 };
verwendet den gleichen Speicher wieprivate List<int> _integers = new List<int> { 1, 2, 3 };
List<T>
hat eineGetEnumerator()
von der Implementierung von getrennte Methode,IEnumerable<T>
die einen veränderlichen Strukturtyp zurückgibtList<T>.Enumerator
. In den meisten Kontexten bietet dieser Typ eine etwas bessere Leistung als ein eigenständiges Heap-Objekt. Compiler, die Enumeratoren vom Ententyp (wie C # und vb.net), können dies beim Generieren vonforeach
Code nutzen. Wenn dieList<T>
gegossen wird ,IEnumrable<T>
bevor dieforeach
, dieIEnumerable<T>.GetEnumerator()
zurückkehrt Methode ein Heap-Objekt zugewiesen, wodurch die Optimierung unmöglich.ICollection<T>
wird verwendet, weil dieIEnumerable<T>
Benutzeroberfläche keine Möglichkeit bietet, Elemente hinzuzufügen, Elemente zu entfernen oder die Sammlung auf andere Weise zu ändern.quelle
List<T>
GeräteICollection<T>
.ICollection
Element erlaubt keine Möglichkeit, Elemente hinzuzufügen, ist jedoch eine nützliche Ergänzung,IEnumerable<T>
da es einCount
Mitglied bereitstellt, das normalerweise viel schneller ist als das Aufzählen aller Elemente . Beachten Sie, dass die Erweiterungsmethode schnell ist , wenn einIList<Cat>
oderICollection<Cat>
an Code übergeben wird, der ein erwartetIEnumerable<Animal>
,Count()
wenn es das nicht generische implementiertICollection
, aber nicht, wenn es nur die generischen Schnittstellen implementiert, da ein typischesICollection<Cat>
nicht implementiert wirdICollection<Animal>
.Beantwortung Ihrer Frage zu
List<T>
:List<T>
ist eine Klasse; Die Angabe einer Schnittstelle ermöglicht eine flexiblere Implementierung. Eine bessere Frage ist "warum nichtIList<T>
?"Um diese Frage zu beantworten, überlegen Sie, was
IList<T>
zurICollection<T>
Ganzzahlindizierung beiträgt. Dies bedeutet, dass die Elemente eine beliebige Reihenfolge haben und unter Bezugnahme auf diese Reihenfolge abgerufen werden können. Dies ist in den meisten Fällen wahrscheinlich nicht sinnvoll, da Artikel in verschiedenen Kontexten wahrscheinlich unterschiedlich bestellt werden müssen.quelle
Es gibt einige grundlegende Unterschiede zwischen ICollection und IEnumerable
Einfaches Programm:
quelle
Ich erinnere mich so:
IEnumerable verfügt über eine Methode GetEnumerator (), mit der die Werte in einer Sammlung gelesen, aber nicht beschrieben werden können. Der größte Teil der Komplexität der Verwendung des Enumerators wird für uns durch die für jede Anweisung in C # erledigt. IEnumerable hat eine Eigenschaft: Current, die das aktuelle Element zurückgibt.
ICollection implementiert IEnumerable und fügt einige zusätzliche Eigenschaften hinzu, von denen Count am häufigsten verwendet wird. Die generische Version von ICollection implementiert die Methoden Add () und Remove ().
IList implementiert sowohl IEnumerable als auch ICollection und fügt den Integer-Indizierungszugriff zu Elementen hinzu (was normalerweise nicht erforderlich ist, da die Bestellung in der Datenbank erfolgt).
quelle
Die Grundidee der Verwendung
ICollection
besteht darin, eine Schnittstelle für den schreibgeschützten Zugriff auf eine begrenzte Datenmenge bereitzustellen. Tatsächlich haben Sie eine ICollection.Count- Eigenschaft.IEnumerable
ist besser geeignet für eine Kette von Daten, in der Sie bis zu einem logischen Punkt, einer vom Verbraucher ausdrücklich angegebenen Bedingung oder bis zum Ende der Aufzählung lesen.quelle
ICollection
schreibgeschützt ist,ICollection<T>
ist es nicht.Navigationseigenschaften werden normalerweise als virtuell definiert, damit sie bestimmte Entity Framework-Funktionen wie z. B. verzögertes Laden nutzen können.
Wenn eine Navigationseigenschaft mehrere Entitäten enthalten kann (wie in Viele-zu-Viele- oder Eins-zu-Viele-Beziehungen), muss ihr Typ eine Liste sein, in der Einträge hinzugefügt, gelöscht und aktualisiert werden können, z. B. ICollection.
https://www.asp.net/mvc/overview/getting-started/getting-started-with-ef-using-mvc/creating-an-entity-framework-data-model-for-an-asp-net- mvc-anwendung
quelle
Was ich in der Vergangenheit getan habe, ist, meine inneren Klassensammlungen mit oder (falls statische Liste) zu deklarieren
IList<Class>
, je nachdem, ob ich in einer Methode in meinem Repository eine der folgenden Aktionen ausführen muss oder nicht : Aufzählen, Sortieren / Ordnen oder Ändern . Wenn ich nur Objekte aufzählen (und möglicherweise sortieren) muss, erstelle ich eine temporäre Datei, um mit der Sammlung innerhalb einer IEnumerable-Methode zu arbeiten. Ich denke, diese Praxis wäre nur dann effektiv, wenn die Sammlung relativ klein ist, aber es kann allgemein eine gute Praxis sein, idk. Bitte korrigieren Sie mich, wenn es Beweise dafür gibt, warum dies keine gute Praxis wäre.ICollection<Class>
IEnumerable<Class>
List<Class>
quelle
Versuchen wir, mit / durch Logik über den Tellerrand hinaus zu denken und diese drei Schnittstellen in Ihrer Frage klar zu verstehen:
Wenn die Klasse einer Instanz die System.Collection.IEnumerable-Schnittstelle implementiert, können wir in einfachen Worten sagen, dass diese Instanz sowohl aufzählbar als auch iterierbar ist, was bedeutet, dass diese Instanz in einer einzelnen Schleife irgendwie zulässt, dass sie geht / get / pass / Durchlaufen / Durchlaufen aller Elemente und Elemente, die diese Instanz enthält.
Dies bedeutet, dass auf diese Weise auch alle in dieser Instanz enthaltenen Elemente und Elemente aufgelistet werden können.
Jede Klasse, die die System.Collection.IEnumerable-Schnittstelle implementiert, implementiert auch die GetEnumerator-Methode, die keine Argumente akzeptiert und eine System.Collections.IEnumerator-Instanz zurückgibt.
Instanzen der System.Collections.IEnumerator-Schnittstelle verhalten sich C ++ - Iteratoren sehr ähnlich.
Wenn die Klasse einer Instanz die System.Collection.ICollection-Schnittstelle implementiert, können wir in einfachen Worten sagen, dass diese Instanz eine Sammlung von Dingen ist.
Die generische Version dieser Schnittstelle, dh System.Collection.Generic.ICollection, ist informativer, da diese generische Schnittstelle explizit angibt, um welche Art von Dingen es sich in der Sammlung handelt.
Dies ist alles vernünftig, rational, logisch und macht Sinn, dass die System.Collections.ICollection-Schnittstelle von der System.Collections.IEnumerable-Schnittstelle erbt, da theoretisch jede Sammlung sowohl aufzählbar als auch iterierbar ist und dies theoretisch möglich ist, alle Elemente und Elemente zu durchlaufen in jeder Sammlung.
Die System.Collections.ICollection-Schnittstelle stellt eine endliche dynamische Sammlung dar, die geändert werden kann. Dies bedeutet, dass vorhandene Elemente aus der Sammlung entfernt und neue Elemente derselben Sammlung hinzugefügt werden können.
Dies erklärt, warum die System.Collections.ICollection-Schnittstelle über die Methoden "Hinzufügen" und "Entfernen" verfügt.
Da diese Instanzen der System.Collections.ICollection-Schnittstelle endliche Sammlungen sind, impliziert das Wort "endlich", dass jede Sammlung dieser Schnittstelle immer eine endliche Anzahl von Elementen und Elementen enthält.
Die Eigenschaft Count of System.Collections.ICollection-Schnittstelle setzt voraus, dass diese Nummer zurückgegeben wird.
Die System.Collections.IEnumerable-Schnittstelle verfügt nicht über diese Methoden und Eigenschaften wie die System.Collections.ICollection-Schnittstelle, da es keinen Sinn macht, dass System.Collections.IEnumerable über diese Methoden und Eigenschaften der System.Collections.ICollection-Schnittstelle verfügt.
Die Logik besagt auch, dass jede Instanz, die sowohl aufzählbar als auch iterierbar ist, nicht unbedingt eine Sammlung ist und nicht unbedingt geändert werden kann.
Wenn ich veränderbar sage, meine ich, dass Sie nicht sofort denken, dass Sie etwas hinzufügen oder entfernen können, das sowohl aufzählbar als auch iterierbar ist.
Wenn ich zum Beispiel nur eine endliche Folge von Primzahlen erstellt habe, ist diese endliche Folge von Primzahlen tatsächlich eine Instanz der System.Collections.IEnumerable-Schnittstelle, da ich jetzt alle Primzahlen in dieser endlichen Folge in einer einzigen Schleife durchgehen kann und mache, was ich mit jedem von ihnen machen will, wie jeden von ihnen auf das Konsolenfenster oder den Bildschirm zu drucken, aber diese endliche Folge von Primzahlen ist keine Instanz der System.Collections.ICollection-Schnittstelle, da dies für keinen Sinn macht Fügen Sie dieser endlichen Folge von Primzahlen zusammengesetzte Zahlen hinzu.
Außerdem möchten Sie in der nächsten Iteration die nächstnächere größere Primzahl zur aktuellen Primzahl in der aktuellen Iteration erhalten. Wenn ja, möchten Sie auch keine vorhandenen Primzahlen aus dieser endlichen Folge von Primzahlen entfernen.
Außerdem möchten Sie wahrscheinlich "Yield Return" in der GetEnumerator-Methode der System.Collections.IEnumerable-Schnittstelle verwenden, codieren und schreiben, um die Primzahlen zu erzeugen und nichts auf dem Speicherheap zuzuweisen, und dann den Garbage Collector (GC) beiden zuweisen Geben Sie die Zuordnung auf und geben Sie diesen Speicher vom Heap frei, da dies offensichtlich sowohl eine Verschwendung des Betriebssystemspeichers als auch eine Verringerung der Leistung darstellt.
Die dynamische Speicherzuweisung und Freigabe auf dem Heap sollte beim Aufrufen der Methoden und Eigenschaften der System.Collections.ICollection-Schnittstelle erfolgen, nicht jedoch beim Aufrufen der Methoden und Eigenschaften der System.Collections.IEnumerable-Schnittstelle (obwohl die System.Collections.IEnumerable-Schnittstelle nur über diese verfügt 1 Methode und 0 Eigenschaften).
Gemäß den Aussagen anderer auf dieser Stack Overflow-Webseite stellt die System.Collections.IList-Schnittstelle lediglich eine bestellbare Sammlung dar. Dies erklärt, warum die Methoden der System.Collections.IList-Schnittstelle im Gegensatz zu denen der System.Collections.ICollection-Schnittstelle mit Indizes arbeiten.
Kurz gesagt, die System.Collections.ICollection-Schnittstelle impliziert nicht, dass eine Instanz davon bestellbar ist, aber die System.Collections.IList-Schnittstelle impliziert dies.
Theoretisch geordnete Menge ist Sonderfall einer ungeordneten Menge.
Dies ist auch sinnvoll und erklärt, warum die System.Collections.IList-Schnittstelle die System.Collections.ICollection-Schnittstelle erbt.
quelle