Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Ähnliche Daten können häufig effizienter verarbeitet werden, wenn sie als Sammlung gespeichert und bearbeitet werden. Sie können die System.Array Klasse oder die Klassen in den System.Collections, System.Collections.Generic, System.Collections.Concurrentund System.Collections.Immutable Namespaces verwenden, um einzelne Elemente oder einen Bereich von Elementen in einer Auflistung hinzuzufügen, zu entfernen und zu ändern.
Es gibt zwei Haupttypen von Sammlungen; generische Auflistungen und nicht generische Auflistungen. Generische Auflistungen sind zur Kompilierungszeit typsicher. Daher bieten generische Sammlungen in der Regel eine bessere Leistung. Generische Auflistungen akzeptieren einen Typparameter, wenn sie erstellt werden. Sie müssen nicht in den Object Typ umwandeln, wenn Sie Elemente aus der Sammlung hinzufügen oder daraus entfernen. Darüber hinaus werden die meisten generischen Sammlungen in Windows Store-Apps unterstützt. Nicht generische Sammlungen speichern Elemente als Object, erfordern Umwandlungen und die meisten werden für die Entwicklung von Windows Store-Apps nicht unterstützt. Möglicherweise werden jedoch nicht generische Auflistungen im älteren Code angezeigt.
In .NET Framework 4 und höheren Versionen bieten die Auflistungen im System.Collections.Concurrent Namespace effiziente threadsichere Vorgänge für den Zugriff auf Sammlungselemente aus mehreren Threads. Die unveränderlichen Auflistungsklassen im System.Collections.Immutable Namespace (NuGet-Paket) sind inhärent threadsicher, da Vorgänge für eine Kopie der ursprünglichen Auflistung ausgeführt werden und die ursprüngliche Auflistung nicht geändert werden kann.
Allgemeine Sammlungsfeatures
Alle Auflistungen stellen Methoden zum Hinzufügen, Entfernen oder Suchen von Elementen in der Auflistung bereit. Darüber hinaus verwenden alle Auflistungen, die die ICollection Schnittstelle oder die ICollection<T> Schnittstelle direkt oder indirekt implementieren, diese Features:
Die Möglichkeit zum Aufzählen der Sammlung
.NET-Auflistungen implementieren System.Collections.IEnumerable oder System.Collections.Generic.IEnumerable<T> aktivieren die Durchlaufen der Auflistung. Ein Enumerator kann als beweglicher Zeiger auf jedes Element in der Sammlung betrachtet werden. Die Foreach, in Anweisung und die For Each... Next Statement verwendet den Enumerator, der von der GetEnumerator Methode verfügbar gemacht wird, und blendet die Komplexität der Bearbeitung des Enumerators aus. Darüber hinaus gilt jede auflistung, die implementiert System.Collections.Generic.IEnumerable<T> wird, als abfragbarer Typ und kann mit LINQ abgefragt werden. LINQ-Abfragen stellen ein gängiges Muster für den Zugriff auf Daten bereit. Sie sind in der Regel präziser und lesbarer als Standardschleifen
foreach
und bieten Filter-, Sortier- und Gruppierungsfunktionen. LINQ-Abfragen können auch die Leistung verbessern. Weitere Informationen finden Sie unter LINQ to Objects (C#),LINQ to Objects (Visual Basic), Parallel LINQ (PLINQ), Introduction to LINQ Queries (C#) und Basic Query Operations (Visual Basic).Die Möglichkeit, den Sammlungsinhalt in ein Array zu kopieren
Alle Auflistungen können mithilfe der
CopyTo
Methode in ein Array kopiert werden. Die Reihenfolge der Elemente im neuen Array basiert jedoch auf der Reihenfolge, in der der Enumerator sie zurückgibt. Das resultierende Array ist immer eindimensional mit einer unteren Grenze von Null.
Darüber hinaus enthalten viele Auflistungsklassen die folgenden Features:
Eigenschaften "Kapazität" und "Anzahl"
Die Kapazität einer Auflistung ist die Anzahl der Elemente, die sie enthalten kann. Die Anzahl einer Auflistung ist die Anzahl der Elemente, die sie tatsächlich enthält. Einige Auflistungen blenden die Kapazität oder die Anzahl oder beides aus.
Die meisten Sammlungen erweitern die Kapazität automatisch, wenn die aktuelle Kapazität erreicht ist. Der Speicher wird neu zugeordnet, und die Elemente werden aus der alten Sammlung in die neue kopiert. Dieser Entwurf reduziert den Code, der für die Verwendung der Auflistung erforderlich ist. Die Leistung der Sammlung kann jedoch negativ beeinflusst werden. Wenn beispielsweise List<T>Count kleiner als Capacity, ist das Hinzufügen eines Elements ein O(1)-Vorgang. Wenn die Kapazität erhöht werden muss, um das neue Element aufzunehmen, wird das Hinzufügen eines Elements zu einem O(
n
)-Vorgang, in demn
sich dies befindet Count. Die beste Methode, um eine schlechte Leistung zu vermeiden, die durch mehrere Reallocations verursacht wird, besteht darin, die anfängliche Kapazität auf die geschätzte Größe der Sammlung festzulegen.A BitArray ist ein Sonderfall; seine Kapazität ist identisch mit der Länge, die mit der Anzahl übereinstimmt.
Eine konsistente untere Grenze
Die untere Grenze einer Auflistung ist der Index des ersten Elements. Alle indizierten Auflistungen in den System.Collections Namespaces weisen eine Untergrenze von Null auf, was bedeutet, dass sie 0 indiziert sind. Array weist standardmäßig eine untere Grenze von Null auf, aber beim Erstellen einer Instanz der Array-KlasseArray.CreateInstancekann eine andere untere Grenze definiert werden.
Synchronisierung für den Zugriff von mehreren Threads (System.Collections nur Klassen).
Nicht generische Sammlungstypen im Namespace bieten eine gewisse Threadsicherheit mit der Synchronisierung; in der System.Collections Regel über die SyncRoot Elemente verfügbar IsSynchronized gemacht. Diese Auflistungen sind standardmäßig nicht threadsicher. Wenn Sie skalierbaren und effizienten Multithreadzugriff auf eine Auflistung benötigen, verwenden Sie eine der Klassen im System.Collections.Concurrent Namespace, oder erwägen Sie die Verwendung einer unveränderlichen Auflistung. Weitere Informationen finden Sie unter Thread-Safe Sammlungen.
Auswählen einer Sammlung
Im Allgemeinen sollten Sie generische Auflistungen verwenden. In der folgenden Tabelle werden einige allgemeine Sammlungsszenarien und die Auflistungsklassen beschrieben, die Sie für diese Szenarien verwenden können. Wenn Sie mit generischen Sammlungen noch nicht vertraut sind, hilft Ihnen die folgende Tabelle bei der Auswahl der generischen Sammlung, die für Ihre Aufgabe am besten geeignet ist:
Ich möchte... | Generische Sammlungsoptionen | Nicht generische Sammlungsoptionen | Threadsichere oder unveränderliche Sammlungsoptionen |
---|---|---|---|
Speichern von Elementen als Schlüssel-Wert-Paare für schnelles Nachschlagen nach Schlüssel | Dictionary<TKey,TValue> | Hashtable (Eine Sammlung von Schlüssel-Wert-Paaren, die basierend auf dem Hashcode des Schlüssels organisiert sind.) |
ConcurrentDictionary<TKey,TValue> ReadOnlyDictionary<TKey,TValue> ImmutableDictionary<TKey,TValue> |
Zugreifen auf Elemente nach Index | List<T> | Array ArrayList |
ImmutableList<T> ImmutableArray |
Verwenden von Elementen first-in-first-out (FIFO) | Queue<T> | Queue | ConcurrentQueue<T> ImmutableQueue<T> |
Verwenden von Daten Last-In-First-Out (LIFO) | Stack<T> | Stack | ConcurrentStack<T> ImmutableStack<T> |
Sequenziell auf Elemente zugreifen | LinkedList<T> | Keine Empfehlung | Keine Empfehlung |
Empfangen von Benachrichtigungen, wenn Elemente entfernt oder der Sammlung hinzugefügt werden. (implementiert INotifyPropertyChanged und INotifyCollectionChanged) | ObservableCollection<T> | Keine Empfehlung | Keine Empfehlung |
Eine sortierte Sammlung | SortedList<TKey,TValue> | SortedList | ImmutableSortedDictionary<TKey,TValue> ImmutableSortedSet<T> |
Ein Satz für mathematische Funktionen | HashSet<T> SortedSet<T> |
Keine Empfehlung | ImmutableHashSet<T> ImmutableSortedSet<T> |
Algorithmische Komplexität von Sammlungen
Bei der Auswahl einer Sammlungsklasse lohnt es sich, potenzielle Kompromisse bei der Leistung zu berücksichtigen. Verwenden Sie die folgende Tabelle, um zu referenzieren, wie verschiedene änderbare Sammlungstypen in algorithmischer Komplexität mit ihren entsprechenden unveränderlichen Gegenstücken verglichen werden. Häufig sind unveränderliche Sammlungstypen weniger leistungsfähig, bieten aber unveränderliche Möglichkeiten , was häufig ein gültiger Vergleichsvorteil ist.
Veränderlich | Amortisiert | Schlimmster Fall | Unveränderbar | Kompliziertheit |
---|---|---|---|---|
Stack<T>.Push |
O(1) | O(n ) |
ImmutableStack<T>.Push |
O(1) |
Queue<T>.Enqueue |
O(1) | O(n ) |
ImmutableQueue<T>.Enqueue |
O(1) |
List<T>.Add |
O(1) | O(n ) |
ImmutableList<T>.Add |
O(log n ) |
List<T>.Item[Int32] |
O(1) | O(1) | ImmutableList<T>.Item[Int32] |
O(log n ) |
List<T>.Enumerator |
O(n ) |
O(n ) |
ImmutableList<T>.Enumerator |
O(n ) |
HashSet<T>.Add nachschlagen |
O(1) | O(n ) |
ImmutableHashSet<T>.Add |
O(log n ) |
SortedSet<T>.Add |
O(log n ) |
O(n ) |
ImmutableSortedSet<T>.Add |
O(log n ) |
Dictionary<T>.Add |
O(1) | O(n ) |
ImmutableDictionary<T>.Add |
O(log n ) |
Dictionary<T> nachschlagen |
O(1) | O(1) – oder streng O(n ) |
ImmutableDictionary<T> nachschlagen |
O(log n ) |
SortedDictionary<T>.Add |
O(log n ) |
O(n Protokoll n ) |
ImmutableSortedDictionary<T>.Add |
O(log n ) |
Eine List<T>
kann mithilfe einer for
Schleife oder einer foreach
Schleife effizient aufgezählt werden. Ein ImmutableList<T>
, jedoch einen schlechten Auftrag innerhalb einer for
Schleife, aufgrund der O(log n
) -Zeit für seinen Indexer. Das Aufzählen einer Verwendung einer ImmutableList<T>
foreach
Schleife ist effizient, da ImmutableList<T>
eine binäre Struktur zum Speichern der Daten anstelle eines Arrays verwendet wird, wie List<T>
es verwendet wird. Ein Array kann schnell indiziert werden, während eine binäre Struktur nach unten geführt werden muss, bis der Knoten mit dem gewünschten Index gefunden wird.
Darüber hinaus hat die gleiche Komplexität wie SortedSet<T>
ImmutableSortedSet<T>
, da beide binäre Strukturen verwenden. Der wesentliche Unterschied besteht darin, dass ImmutableSortedSet<T>
eine unveränderliche binäre Struktur verwendet wird. Da ImmutableSortedSet<T>
sie auch eine System.Collections.Immutable.ImmutableSortedSet<T>.Builder Klasse bietet, die Mutationen zulässt, können Sie sowohl Unveränderlichkeit als auch Leistung haben.
Verwandte Artikel
Titel | BESCHREIBUNG |
---|---|
Auswählen einer Sammlungsklasse | Beschreibt die verschiedenen Sammlungen und hilft Ihnen bei der Auswahl eines für Ihr Szenario. |
Häufig verwendete Sammlungstypen | Beschreibt häufig verwendete generische und nicht generische Sammlungstypen, z System.Array. B. , System.Collections.Generic.List<T>und System.Collections.Generic.Dictionary<TKey,TValue>. |
Gründe für die Verwendung generischer Sammlungen | Erläutert die Verwendung generischer Auflistungstypen. |
Vergleiche und Sortierungen innerhalb von Sammlungen | Erläutert die Verwendung von Gleichheitsvergleichen und Sortiervergleichen in Auflistungen. |
Sortierte Auflistungstypen | Beschreibt die Leistung und Merkmale sortierter Auflistungen. |
Hashtable- und Dictionary-Sammlungstypen | Beschreibt die Features generischer und nicht generischer hashbasierter Wörterbuchtypen. |
Thread-Safe Sammlungen | Beschreibt Sammlungstypen, z System.Collections.Concurrent.BlockingCollection<T> . B. und System.Collections.Concurrent.ConcurrentBag<T> die den sicheren und effizienten gleichzeitigen Zugriff von mehreren Threads unterstützen. |
System.Collections.Immutable | Führt die unveränderlichen Auflistungen ein und stellt Links zu den Auflistungstypen bereit. |