Verzamelingen en gegevensstructuren
Vergelijkbare gegevens kunnen vaak efficiënter worden verwerkt wanneer ze worden opgeslagen en gemanipuleerd als verzameling. U kunt de System.Array klasse of de klassen in de System.Collections, System.Collections.Genericen System.Collections.ConcurrentSystem.Collections.Immutable naamruimten gebruiken om afzonderlijke elementen of een reeks elementen in een verzameling toe te voegen, te verwijderen en te wijzigen.
Er zijn twee hoofdtypen verzamelingen; algemene verzamelingen en niet-generieke verzamelingen. Algemene verzamelingen zijn typeveilig tijdens het compileren. Hierdoor bieden algemene verzamelingen doorgaans betere prestaties. Algemene verzamelingen accepteren een typeparameter wanneer ze zijn samengesteld en u hoeft niet te casten naar en van het Object type wanneer u items aan de verzameling toevoegt of verwijdert. Daarnaast worden de meeste algemene verzamelingen ondersteund in Windows Store-apps. Niet-generieke verzamelingen store-items alsObject, vereisen cast-conversie en de meeste worden niet ondersteund voor Windows Store-app-ontwikkeling. Mogelijk ziet u echter niet-algemene verzamelingen in oudere code.
Vanaf .NET Framework 4 bieden de verzamelingen in de System.Collections.Concurrent naamruimte efficiënte thread-veilige bewerkingen voor toegang tot verzamelingsitems uit meerdere threads. De onveranderbare verzamelingsklassen in de System.Collections.Immutable naamruimte (NuGet-pakket) zijn inherent thread-safe omdat bewerkingen worden uitgevoerd op een kopie van de oorspronkelijke verzameling en de oorspronkelijke verzameling niet kan worden gewijzigd.
Algemene verzamelingsfuncties
Alle verzamelingen bieden methoden voor het toevoegen, verwijderen of zoeken van items in de verzameling. Daarnaast delen alle verzamelingen die direct of indirect de ICollection interface of de ICollection<T> interface deze functies delen:
De mogelijkheid om de verzameling op te sommen
.NET-verzamelingen implementeren System.Collections.IEnumerable of System.Collections.Generic.IEnumerable<T> inschakelen dat de verzameling kan worden doorlopen. Een enumerator kan worden beschouwd als een beweegbare aanwijzer naar elk element in de verzameling. De foreach, in statement en de For Each... Volgende instructie gebruikt de enumerator die door de GetEnumerator methode wordt weergegeven en verberg de complexiteit van het bewerken van de enumerator. Bovendien wordt elke verzameling die wordt geïmplementeerd System.Collections.Generic.IEnumerable<T> , beschouwd als een querybaar type en kan worden opgevraagd met LINQ. LINQ-query's bieden een gemeenschappelijk patroon voor toegang tot gegevens. Ze zijn doorgaans beknopter en leesbaarder dan standaardlussen
foreach
en bieden mogelijkheden voor filteren, ordenen en groeperen. LINQ-query's kunnen ook de prestaties verbeteren. Zie LINQ to Objects (C#), LINQ to Objects (Visual Basic), Parallel LINQ (PLINQ), Inleiding tot LINQ-query's (C#) en Basic Query Operations (Visual Basic)) voor meer informatie.De mogelijkheid om de inhoud van de verzameling te kopiëren naar een matrix
Alle verzamelingen kunnen worden gekopieerd naar een matrix met behulp van de methode CopyTo ; de volgorde van de elementen in de nieuwe matrix is echter gebaseerd op de volgorde waarin de enumerator deze retourneert. De resulterende matrix is altijd eendimensionaal met een ondergrens van nul.
Daarnaast bevatten veel verzamelingsklassen de volgende functies:
Eigenschappen voor capaciteit en aantal
De capaciteit van een verzameling is het aantal elementen dat deze kan bevatten. Het aantal van een verzameling is het aantal elementen dat deze daadwerkelijk bevat. Sommige verzamelingen verbergen de capaciteit of het aantal of beide.
De meeste verzamelingen worden automatisch uitgebreid in capaciteit wanneer de huidige capaciteit wordt bereikt. Het geheugen is opnieuw toegewezen en de elementen worden gekopieerd van de oude verzameling naar de nieuwe verzameling. Dit vermindert de code die nodig is voor het gebruik van de verzameling; De prestaties van de verzameling kunnen echter negatief worden beïnvloed. Als een item bijvoorbeeld List<T>Count kleiner is danCapacity, is het toevoegen van een item een O(1)-bewerking. Als de capaciteit moet worden verhoogd om tegemoet te komen aan het nieuwe element, wordt het toevoegen van een item een O(
n
)-bewerking, waarn
.Count De beste manier om slechte prestaties te voorkomen die worden veroorzaakt door meerdere toewijzingen, is door de aanvankelijke capaciteit in te stellen op de geschatte grootte van de verzameling.A BitArray is een speciaal geval; de capaciteit is hetzelfde als de lengte, die gelijk is aan het aantal.
Een consistente ondergrens
De ondergrens van een verzameling is de index van het eerste element. Alle geïndexeerde verzamelingen in de System.Collections naamruimten hebben een ondergrens van nul, wat betekent dat ze 0-geïndexeerd zijn. Array heeft standaard een ondergrens van nul, maar een andere ondergrens kan worden gedefinieerd bij het maken van een exemplaar van de matrixklasse met behulp van Array.CreateInstance.
Synchronisatie voor toegang vanaf meerdere threads (System.Collections alleen klassen).
Niet-algemene verzamelingstypen in de System.Collections naamruimte bieden een zekere veiligheid van threads met synchronisatie, meestal beschikbaar via de SyncRoot en IsSynchronized leden. Deze verzamelingen zijn standaard niet thread-veilig. Als u schaalbare en efficiënte toegang met meerdere threads tot een verzameling nodig hebt, gebruikt u een van de klassen in de System.Collections.Concurrent naamruimte of kunt u overwegen een onveranderbare verzameling te gebruiken. Zie Thread-Safe Collections voor meer informatie.
Een verzameling kiezen
Over het algemeen moet u algemene verzamelingen gebruiken. In de volgende tabel worden enkele veelvoorkomende verzamelingsscenario's en de verzamelingsklassen beschreven die u voor deze scenario's kunt gebruiken. Als u geen toegang hebt tot algemene verzamelingen, helpt deze tabel u bij het kiezen van de algemene verzameling die het beste werkt voor uw taak.
Ik wil... | Algemene verzamelingsopties | Niet-algemene verzamelingsopties | Opties voor thread-veilige of onveranderbare verzameling |
---|---|---|---|
Items opslaan als sleutel-waardeparen voor snel opzoeken op sleutel | Dictionary<TKey,TValue> | Hashtable (Een verzameling sleutel-waardeparen die zijn geordend op basis van de hashcode van de sleutel.) |
ConcurrentDictionary<TKey,TValue> ReadOnlyDictionary<TKey,TValue> ImmutableDictionary<TKey,TValue> |
Toegang tot items per index | List<T> | Array ArrayList |
ImmutableList<T> ImmutableArray |
Items first-in-first-out (FIFO) gebruiken | Queue<T> | Queue | ConcurrentQueue<T> ImmutableQueue<T> |
Gegevens last-in-first-out (LIFO) gebruiken | Stack<T> | Stack | ConcurrentStack<T> ImmutableStack<T> |
Items opeenvolgend openen | LinkedList<T> | Geen aanbeveling | Geen aanbeveling |
Ontvang meldingen wanneer items worden verwijderd of toegevoegd aan de verzameling. (implementeert INotifyPropertyChanged en INotifyCollectionChanged) | ObservableCollection<T> | Geen aanbeveling | Geen aanbeveling |
Een gesorteerde verzameling | SortedList<TKey,TValue> | SortedList | ImmutableSortedDictionary<TKey,TValue> ImmutableSortedSet<T> |
Een set voor wiskundige functies | HashSet<T> SortedSet<T> |
Geen aanbeveling | ImmutableHashSet<T> ImmutableSortedSet<T> |
Algoritmecomplexiteit van verzamelingen
Bij het kiezen van een verzamelingsklasse is het de moeite waard om mogelijke compromissen in prestaties te overwegen. Gebruik de volgende tabel om te verwijzen naar de vergelijking van verschillende veranderlijke verzamelingstypen in algoritmecomplexiteit met de bijbehorende onveranderbare tegenhangers. Vaak zijn onveranderbare verzamelingstypen minder goed presterend, maar bieden onveranderbaarheid, wat vaak een geldig vergelijkend voordeel is.
Veranderlijk | Afgeschreven | Slechtste geval | Onveranderlijke | Complexiteit |
---|---|---|---|---|
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(logboek n ) |
List<T>.Item[Int32] |
O(1) | O(1) | ImmutableList<T>.Item[Int32] |
O(logboek n ) |
List<T>.Enumerator |
O(n ) |
O(n ) |
ImmutableList<T>.Enumerator |
O(n ) |
HashSet<T>.Add Lookup |
O(1) | O(n ) |
ImmutableHashSet<T>.Add |
O(logboek n ) |
SortedSet<T>.Add |
O(logboek n ) |
O(n ) |
ImmutableSortedSet<T>.Add |
O(logboek n ) |
Dictionary<T>.Add |
O(1) | O(n ) |
ImmutableDictionary<T>.Add |
O(logboek n ) |
Dictionary<T> Lookup |
O(1) | O(1) – of strikt O(n ) |
ImmutableDictionary<T> Lookup |
O(logboek n ) |
SortedDictionary<T>.Add |
O(logboek n ) |
O(n logboek n ) |
ImmutableSortedDictionary<T>.Add |
O(logboek n ) |
Een List<T>
kan efficiënt worden geïnventariseerd met behulp van een for
lus of een foreach
lus. Een ImmutableList<T>
, echter, doet een slechte taak binnen een for
lus, vanwege de O(logboek n
) tijd voor de indexeerfunctie. Het inventariseren van een ImmutableList<T>
foreach
lus is efficiënt omdat ImmutableList<T>
een binaire structuur wordt gebruikt om de gegevens op te slaan in plaats van een eenvoudige matrix, zoals List<T>
gebruikt. Een matrix kan zeer snel worden geïndexeerd, terwijl een binaire structuur moet worden doorlopen totdat het knooppunt met de gewenste index wordt gevonden.
SortedSet<T>
Bovendien heeft dezelfde complexiteit als ImmutableSortedSet<T>
. Dat komt omdat ze beide binaire bomen gebruiken. Het grote verschil is natuurlijk dat ImmutableSortedSet<T>
een onveranderbare binaire structuur wordt gebruikt. Omdat ImmutableSortedSet<T>
u ook een System.Collections.Immutable.ImmutableSortedSet<T>.Builder klasse biedt die mutatie toestaat, kunt u zowel onveranderbaarheid als prestaties hebben.
Verwante onderwerpen
Titel | Beschrijving |
---|---|
Een verzamelingsklasse selecteren | Hierin worden de verschillende verzamelingen beschreven en kunt u er een selecteren voor uw scenario. |
Veelgebruikte verzamelingstypen | Beschrijft veelgebruikte algemene en niet-generische verzamelingstypen zoals System.Array, System.Collections.Generic.List<T>en System.Collections.Generic.Dictionary<TKey,TValue>. |
Wanneer algemene verzamelingen gebruiken | Hiermee wordt het gebruik van algemene verzamelingstypen besproken. |
Vergelijkingen en sorteringen binnen verzamelingen | Beschrijft het gebruik van gelijkheidsvergelijkingen en sorteervergelijkingen in verzamelingen. |
Gesorteerde verzamelingstypen | Beschrijft de prestaties en kenmerken van gesorteerde verzamelingen |
Typen hashtabel- en woordenlijstverzameling | Beschrijft de functies van algemene en niet-generieke op hash gebaseerde woordenlijsttypen. |
Thread-Safe-verzamelingen | Beschrijft verzamelingstypen zoals System.Collections.Concurrent.BlockingCollection<T> en System.Collections.Concurrent.ConcurrentBag<T> die veilige en efficiënte gelijktijdige toegang vanuit meerdere threads ondersteunen. |
System.Collections.Immutable | Introduceert de onveranderbare verzamelingen en biedt koppelingen naar de verzamelingstypen. |
Verwijzing
System.Array System.Collections System.Collections.Concurrent System.Collections.Generic System.Collections.Specialized System.Linq System.Collections.Immutable