Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
I dati simili possono spesso essere gestiti in modo più efficiente quando vengono archiviati e modificati come raccolta. È possibile usare la classe System.Array o le classi nei namespace System.Collections, System.Collections.Generic, System.Collections.Concurrent e System.Collections.Immutable per aggiungere, rimuovere e modificare singoli elementi o un intervallo di elementi in una raccolta.
Esistono due tipi principali di raccolte; raccolte generiche e raccolte non generiche. Le raccolte generiche sono sicure per i tipi in fase di compilazione. Per questo motivo, le raccolte generiche offrono in genere prestazioni migliori. Le raccolte generiche accettano un parametro di tipo quando vengono costruite. Non richiedono il cast da e verso il Object tipo quando si aggiungono o si rimuovono elementi dalla raccolta. Inoltre, la maggior parte delle raccolte generiche è supportata nelle app di Windows Store. Le raccolte non generiche archiviano gli elementi come Object, richiedono il cast e la maggior parte non sono supportate per lo sviluppo di app di Windows Store. Tuttavia, è possibile che nel codice precedente vengano visualizzate raccolte non generiche.
In .NET Framework 4 e nelle versioni successive, le raccolte del namespace System.Collections.Concurrent forniscono operazioni efficienti sicure per i thread per l'accesso agli elementi della raccolta da più thread. Le classi di raccolta non modificabili nello spazio dei nomi System.Collections.Immutable (pacchetto NuGet) sono intrinsecamente thread-safe perché le operazioni vengono eseguite su una copia di essa e la raccolta originale non può essere modificata.
Funzionalità comuni delle collezioni
Tutte le raccolte forniscono metodi per l'aggiunta, la rimozione o la ricerca di elementi nella raccolta. Inoltre, tutte le raccolte che implementano direttamente o indirettamente l'interfaccia ICollection o l'interfaccia ICollection<T> condividono queste funzionalità:
Possibilità di enumerare la raccolta
Le raccolte .NET implementano System.Collections.IEnumerable o System.Collections.Generic.IEnumerable<T> per consentire l'iterazione della raccolta. Un enumeratore può essere considerato come un puntatore mobile a qualsiasi elemento della raccolta. La istruzione foreach, in e la istruzione For Each... Next usano l'enumeratore esposto dal GetEnumerator metodo e nascondono la complessità della manipolazione dell'enumeratore. Inoltre, qualsiasi raccolta che implementa System.Collections.Generic.IEnumerable<T> viene considerata un tipo queryable e può essere interrogata con LINQ. Le query LINQ forniscono un modello comune per l'accesso ai dati. In genere sono più concisi e leggibili rispetto ai cicli standard
foreache forniscono funzionalità di filtro, ordinamento e raggruppamento. Le query LINQ possono anche migliorare le prestazioni. Per altre informazioni, vedere LINQ to Objects (C#),LINQ to Objects (Visual Basic), Parallel LINQ (PLINQ),Introduction to LINQ Queries (C#) e Basic Query Operations (Visual Basic).Possibilità di copiare il contenuto della raccolta in una matrice
È possibile copiare tutte le raccolte in una matrice usando il
CopyTometodo . Tuttavia, l'ordine degli elementi nella nuova matrice si basa sulla sequenza in cui l'enumeratore li restituisce. La matrice risultante è sempre unidimensionale con un limite inferiore pari a zero.
Inoltre, molte classi di raccolta contengono le funzionalità seguenti:
Proprietà Capacità e Conteggio
La capacità di una raccolta è il numero di elementi che può contenere. Il conteggio di una raccolta è il numero di elementi effettivamente contenuti. Alcune raccolte nascondono la capacità o il conteggio o entrambi.
La maggior parte delle raccolte si espande automaticamente in capacità quando si raggiunge la capacità corrente. La memoria viene riallocata e gli elementi vengono copiati dalla raccolta precedente a quella nuova. Questa progettazione riduce il codice necessario per usare la raccolta. Tuttavia, le prestazioni della raccolta potrebbero essere influenzate negativamente. Ad esempio, per List<T>, se Count è minore di Capacity, l'aggiunta di un elemento è un'operazione O(1). Se la capacità deve essere aumentata per contenere il nuovo elemento, l'aggiunta di un elemento diventa un'operazione O(
n), dovenè Count. Il modo migliore per evitare prestazioni scarse causate da più riallocazioni consiste nell'impostare la capacità iniziale in modo che sia la dimensione stimata della raccolta.Un BitArray è un caso speciale; la sua capacità è la stessa della sua lunghezza, che corrisponde al conteggio.
Un limite inferiore coerente
Il limite inferiore di una raccolta è l'indice del primo elemento. Tutte le raccolte indicizzate nei namespace System.Collections hanno un limite inferiore pari a zero, il che significa che sono indicizzate a partire da 0. Array ha un limite inferiore di zero per impostazione predefinita, ma è possibile definire un limite inferiore diverso quando si crea un'istanza della classe Array usando Array.CreateInstance.
Sincronizzazione per l'accesso da più thread (System.Collections solo classi).
I tipi di raccolta non generici nello System.Collections spazio dei nomi forniscono alcune misure di thread safety con sincronizzazione, solitamente esposti attraverso i membri SyncRoot e IsSynchronized. Queste raccolte non sono thread-safe per impostazione predefinita. Se è necessario un accesso multithread scalabile ed efficiente a una raccolta, usare una delle classi nello spazio dei nomi System.Collections.Concurrent o considerare l'uso di una raccolta non modificabile. Per altre informazioni, vedere raccolteThread-Safe.
Scegliere una raccolta
In generale, è consigliabile usare raccolte generiche. Nella tabella seguente vengono descritti alcuni scenari comuni di raccolta e le classi di raccolta che è possibile usare per tali scenari. Se non si ha familiarità con le raccolte generiche, la tabella seguente consente di scegliere la raccolta generica più adatta per l'attività:
| Vorrei... | Opzioni di raccolta generica | Opzioni di raccolta non generica | Opzioni di raccolta thread-safe o non modificabili |
|---|---|---|---|
| Archiviare gli elementi come coppie chiave/valore per una ricerca rapida in base alla chiave | Dictionary<TKey,TValue> | Hashtable Raccolta di coppie chiave/valore organizzate in base al codice hash della chiave. |
ConcurrentDictionary<TKey,TValue> ReadOnlyDictionary<TKey,TValue> ImmutableDictionary<TKey,TValue> |
| Accedere agli elementi in base all'indice | List<T> | Array ArrayList |
ImmutableList<T> ImmutableArray |
| Usare gli elementi in modalità 'primo entro, primo fuori' (FIFO) | Queue<T> | Queue | ConcurrentQueue<T> ImmutableQueue<T> |
| Usare i dati last-in-First-Out (LIFO) | Stack<T> | Stack | ConcurrentStack<T> ImmutableStack<T> |
| Accedere agli elementi in sequenza | LinkedList<T> | Nessuna raccomandazione | Nessuna raccomandazione |
| Ricevere notifiche quando gli elementi vengono rimossi o aggiunti alla raccolta. (implementa INotifyPropertyChanged e INotifyCollectionChanged) | ObservableCollection<T> | Nessuna raccomandazione | Nessuna raccomandazione |
| Raccolta ordinata | SortedList<TKey,TValue> | SortedList | ImmutableSortedDictionary<TKey,TValue> ImmutableSortedSet<T> |
| Set per le funzioni matematiche | HashSet<T> SortedSet<T> |
Nessuna raccomandazione | ImmutableHashSet<T> ImmutableSortedSet<T> |
Complessità algoritmica delle raccolte
Quando si sceglie una classe di raccolta, vale la pena considerare potenziali compromessi nelle prestazioni. Usare la tabella seguente per fare riferimento al confronto tra i vari tipi di raccolta modificabili nella complessità algoritmica con le corrispondenti controparti non modificabili. Spesso i tipi di raccolta non modificabili sono meno efficienti, ma offrono immutabilità, che spesso è un vantaggio comparativo valido.
| Modificabile | Ammortizzato | Caso peggiore | Immutabile | Complessità |
|---|---|---|---|---|
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>.AddRicerca |
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> Ricerca |
O(1) | O(1) – o rigorosamente O(n) |
ImmutableDictionary<T> Ricerca |
O(log n) |
SortedDictionary<T>.Add |
O(log n) |
O(n log n) |
ImmutableSortedDictionary<T>.Add |
O(log n) |
Un oggetto List<T> può essere enumerato in modo efficiente usando un ciclo for o un ciclo foreach. Un ImmutableList<T>oggetto , tuttavia, esegue un processo non ottimale all'interno di un for ciclo, a causa del tempo di O(log n) per il relativo indicizzatore. Enumerare un ImmutableList<T> utilizzando un ciclo foreach è efficiente perché ImmutableList<T> utilizza un albero binario per archiviare i dati anziché una matrice come fa List<T>. Una matrice può essere indicizzata rapidamente, mentre un albero binario deve essere percorso fino a quando non viene trovato il nodo con l'indice desiderato.
Inoltre, SortedSet<T> ha la stessa complessità di ImmutableSortedSet<T> perché entrambi usano alberi binari. La differenza significativa è che ImmutableSortedSet<T> usa un albero binario non modificabile. Poiché ImmutableSortedSet<T> offre anche una classe che consente la System.Collections.Immutable.ImmutableSortedSet<T>.Builder mutazione, è possibile avere sia immutabilità che prestazioni.
Articoli correlati
| Titolo | Descrizione |
|---|---|
| Selezione di una classe di raccolta | Descrive le diverse raccolte e consente di selezionare una per lo scenario. |
| Tipi di raccolta di uso comune | Descrive i tipi di raccolta generici e non generici di uso comune, come System.Array, System.Collections.Generic.List<T> e System.Collections.Generic.Dictionary<TKey,TValue>. |
| Quando usare raccolte generiche | Viene illustrato l'uso di tipi di raccolta generici. |
| Confronti e ordinamenti all'interno di raccolte | Illustra l'uso di confronti di uguaglianza e confronti di ordinamento nelle raccolte. |
| Tipi di raccolta ordinati | Vengono descritte le prestazioni e le caratteristiche delle raccolte ordinate. |
| Tipi di raccolta Hashtable e Dictionary | Vengono descritte le funzionalità dei tipi di dizionario generici e non generici basati su hash. |
| RaccolteThread-Safe | Descrive i tipi di raccolta, System.Collections.Concurrent.BlockingCollection<T> ad esempio e System.Collections.Concurrent.ConcurrentBag<T> che supportano l'accesso simultaneo sicuro ed efficiente da più thread. |
| System.Collections.Immutable | Introduce le raccolte non modificabili e fornisce collegamenti ai tipi di raccolta. |