Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Podobne dane mogą być często obsługiwane wydajniej podczas przechowywania i manipulowania nimi jako kolekcji. Możesz użyć klasy System.Array lub klas w przestrzeniach nazw System.Collections, System.Collections.Generic, System.Collections.Concurrent i System.Collections.Immutable do dodawania, usuwania i modyfikowania pojedynczych elementów lub całego zakresu elementów w kolekcji.
Istnieją dwa główne typy kolekcji; kolekcje ogólne i kolekcje inne niż ogólne. Kolekcje ogólne są bezpieczne w czasie kompilacji. W związku z tym kolekcje ogólne zwykle oferują lepszą wydajność. Kolekcje ogólne akceptują parametr typu podczas ich konstruowania. Nie wymagają rzutowania do i z Object typu podczas dodawania lub usuwania elementów z kolekcji. Ponadto większość kolekcji ogólnych jest obsługiwana w aplikacjach ze Sklepu Windows. Kolekcje niegeneryczne przechowują elementy jako Object, wymagają rzutowania i większość z nich nie jest obsługiwana w przypadku tworzenia aplikacji Sklepu Windows. Jednak w starszym kodzie mogą być widoczne kolekcje niemające ogólnego charakteru.
W .NET Framework 4 i nowszych wersjach kolekcje w przestrzeni nazw System.Collections.Concurrent zapewniają wydajne, bezpieczne dla wątków operacje do uzyskiwania dostępu do elementów kolekcji z różnych wątków. Niezmienne klasy kolekcji w System.Collections.Immutable przestrzeni nazw (pakiet NuGet) są z natury bezpieczne wątkowo, ponieważ operacje są wykonywane na kopii oryginalnej kolekcji, a oryginalna kolekcja nie może być modyfikowana.
Typowe funkcje kolekcji
Wszystkie kolekcje zapewniają metody dodawania, usuwania lub znajdowania elementów w kolekcji. Ponadto wszystkie kolekcje bezpośrednio lub pośrednio implementujące ICollection interfejs lub ICollection<T> interfejs współużytkują następujące funkcje:
Możliwość wyliczania kolekcji
Kolekcje platformy .NET implementują System.Collections.IEnumerable lub System.Collections.Generic.IEnumerable<T>, umożliwiając iterowanie kolekcji. Wyliczacz można traktować jako ruchomy wskaźnik do dowolnego elementu w kolekcji. foreach, w instrukcji i For Each...Next używa wylicznika udostępnianego przez GetEnumerator metodę i ukrywa złożoność manipulowania wylicznikiem. Ponadto każda kolekcja, która implementuje System.Collections.Generic.IEnumerable<T> , jest traktowana jako typ z możliwością wykonywania zapytań i może być odpytywalna za pomocą LINQ. Zapytania LINQ zapewniają wspólny wzorzec uzyskiwania dostępu do danych. Zazwyczaj są one bardziej zwięzłe i czytelne niż
foreach
standardowe pętle i zapewniają możliwości filtrowania, porządkowania i grupowania. Zapytania LINQ mogą również zwiększyć wydajność. Aby uzyskać więcej informacji, zobacz LINQ to Objects (C#),LINQ to Objects (Visual Basic),Parallel LINQ (PLINQ), Wprowadzenie do zapytań LINQ (C#) i Podstawowe operacje zapytań (Visual Basic).Możliwość kopiowania zawartości kolekcji do tablicy
Wszystkie kolekcje można skopiować do tablicy przy użyciu metody
CopyTo
. Jednak kolejność elementów w nowej tablicy jest oparta na sekwencji, w której moduł wyliczający je zwraca. Wynikowa tablica jest zawsze jednowymiarowa z dolną granicą zera.
Ponadto wiele klas kolekcji zawiera następujące funkcje:
Właściwości pojemności i liczby
Pojemność kolekcji to liczba elementów, które może zawierać. Liczba kolekcji jest liczbą elementów, które faktycznie zawiera. Niektóre kolekcje ukrywają pojemność, liczbę lub oba te elementy.
Większość kolekcji automatycznie rozszerza pojemność po osiągnięciu bieżącej pojemności. Pamięć jest ponownie przydzielana, a elementy są kopiowane ze starej kolekcji do nowej. Ten projekt zmniejsza kod wymagany do korzystania z kolekcji. Jednak wydajność kolekcji może mieć negatywny wpływ. Na przykład, dla elementu List<T>, jeśli wartość Count jest mniejsza niż Capacity, dodanie elementu jest operacją O(1). Jeśli pojemność musi zostać zwiększona, aby uwzględnić nowy element, dodanie elementu stanie się operacją O(
n
), gdzien
to Count. Najlepszym sposobem uniknięcia słabej wydajności spowodowanej przez wiele realokacji jest ustawienie początkowej pojemności na szacowany rozmiar kolekcji.BitArray to szczególny przypadek; jego pojemność jest taka sama jak jego długość, co jest takie samo jak jego liczebność.
Spójna dolna granica
Dolna granica kolekcji jest indeksem pierwszego elementu. Wszystkie indeksowane kolekcje w System.Collections namespace'ach mają indeks początkowy równy zero, co oznacza, że są indeksowane od zera. Array domyślnie ma dolną granicę zera, ale można zdefiniować inną dolną granicę podczas tworzenia wystąpienia klasy Array przy użyciu polecenia Array.CreateInstance.
Synchronizacja dostępu z wielu wątków (tylko dla System.Collections klas).
Nieogólne typy kolekcji w przestrzeni nazw System.Collections zapewniają pewne bezpieczeństwo wątków dzięki synchronizacji; zazwyczaj udostępniane są za pośrednictwem członków SyncRoot i IsSynchronized. Te kolekcje nie są domyślnie bezpieczne dla wątków. Jeśli potrzebujesz skalowalnego i wydajnego wielowątkowego dostępu do kolekcji, użyj jednej z klas w System.Collections.Concurrent przestrzeni nazw lub rozważ użycie niezmiennej kolekcji. Aby uzyskać więcej informacji, zobacz Thread-Safe Kolekcje.
Wybieranie kolekcji
Ogólnie rzecz biorąc, należy używać kolekcji ogólnych. W poniższej tabeli opisano niektóre typowe scenariusze kolekcji i klasy kolekcji, których można użyć w tych scenariuszach. Jeśli dopiero zaczynasz korzystać z kolekcji ogólnych, poniższa tabela pomoże Ci wybrać kolekcję ogólną, która najlepiej sprawdza się w twoim zadaniu:
Chcę... | Opcje kolekcji ogólnej | Opcje kolekcji nieogólne | Opcje kolekcji, które są bezpieczne dla wątków lub niezmienne |
---|---|---|---|
Przechowywanie elementów jako par klucz/wartość w celu szybkiego wyszukiwania według klucza | Dictionary<TKey,TValue> | Hashtable (Kolekcja par klucz/wartość, które są zorganizowane na podstawie kodu skrótu klucza). |
ConcurrentDictionary<TKey,TValue> ReadOnlyDictionary<TKey,TValue> ImmutableDictionary<TKey,TValue> |
Uzyskiwanie dostępu do elementów według indeksu | List<T> | Array ArrayList |
ImmutableList<T> ImmutableArray |
Stosowanie zasady pierwsze weszło, pierwsze wyszło (FIFO) | Queue<T> | Queue | ConcurrentQueue<T> ImmutableQueue<T> |
Korzystanie z danych last-in-First-Out (LIFO) | Stack<T> | Stack | ConcurrentStack<T> ImmutableStack<T> |
Sekwencyjnie uzyskiwanie dostępu do elementów | LinkedList<T> | Brak rekomendacji | Brak rekomendacji |
Otrzymywanie powiadomień, gdy elementy zostaną usunięte lub dodane do kolekcji. (implementuje INotifyPropertyChanged i INotifyCollectionChanged) | ObservableCollection<T> | Brak rekomendacji | Brak rekomendacji |
Posortowana kolekcja | SortedList<TKey,TValue> | SortedList | ImmutableSortedDictionary<TKey,TValue> ImmutableSortedSet<T> |
Zestaw funkcji matematycznych | HashSet<T> SortedSet<T> |
Brak rekomendacji | ImmutableHashSet<T> ImmutableSortedSet<T> |
Algorytmiczna złożoność kolekcji
Podczas wybierania klasy kolekcji warto rozważyć potencjalne kompromisy w wydajności. Skorzystaj z poniższej tabeli, aby dowiedzieć się, jak różne typy kolekcji modyfikowalne porównują się ze złożonością algorytmiczną do odpowiadających im niezmiennych odpowiedników. Często niezmienne typy kolekcji są mniej wydajne, ale zapewniają niezmienność — co często jest prawidłową korzyścią porównawczą.
Modyfikowalny | Amortyzowane | Najgorszy przypadek | Niezmienialny | Złożoność |
---|---|---|---|---|
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 Wyszukaj |
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> Wyszukiwanie |
O(1) | O(1) — lub ściśle O(n ) |
ImmutableDictionary<T> Wyszukiwanie |
O(log n ) |
SortedDictionary<T>.Add |
O(log n ) |
O(n dziennik n ) |
ImmutableSortedDictionary<T>.Add |
O(log n ) |
Element List<T>
może być skutecznie wyliczany przy użyciu for
pętli lub foreach
pętli. Element ImmutableList<T>
, jednak wykonuje słabe zadanie wewnątrz for
pętli ze względu na czas O(log n
) dla indeksatora. Wyliczanie ImmutableList<T>
przy użyciu pętli foreach
jest wydajne, ponieważ ImmutableList<T>
używa drzewa binarnego do przechowywania danych zamiast tablicy, którą wykorzystuje List<T>
. Tablicę można szybko indeksować, podczas gdy drzewo binarne musi być przechodzine w dół do momentu znalezienia węzła z żądanym indeksem.
Dodatkowo, SortedSet<T>
ma taką samą złożoność jak ImmutableSortedSet<T>
, ponieważ oba używają drzew binarnych. Znacząca różnica polega na tym, że ImmutableSortedSet<T>
używa niezmiennego drzewa binarnego. Ponieważ ImmutableSortedSet<T>
oferuje również klasę, która umożliwia mutację System.Collections.Immutable.ImmutableSortedSet<T>.Builder , można mieć zarówno niezmienność, jak i wydajność.
Powiązane artykuły
Nazwa | Opis |
---|---|
Wybieranie klasy kolekcji | Opisuje różne kolekcje i pomaga wybrać jedną z nich dla danego scenariusza. |
Często używane typy kolekcji | Opisuje powszechnie używane typy kolekcji ogólnych i nieogólne, takie jak System.Array, System.Collections.Generic.List<T>i System.Collections.Generic.Dictionary<TKey,TValue>. |
Kiedy należy używać kolekcji ogólnych | Omówienie użycia typów kolekcji ogólnych. |
Porównania i sortowanie w kolekcjach | Omawia użycie porównań równości i sortowania w kolekcjach. |
Sortowane typy kolekcji | Opisuje wydajność i właściwości posortowanych kolekcji. |
Typy kolekcji tabel skrótów i słowników | Opisuje funkcje ogólnych i niegenerycznych typów słowników opartych na skrótach. |
Thread-Safe kolekcje | Opisuje typy kolekcji, takie jak System.Collections.Concurrent.BlockingCollection<T> i System.Collections.Concurrent.ConcurrentBag<T> , które obsługują bezpieczny i wydajny współbieżny dostęp z wielu wątków. |
System.Collections.Immutable | Wprowadza niezmienne kolekcje i udostępnia linki do typów kolekcji. |