Condividi tramite


Enumerazione di una raccolta

.NET Framework fornisce enumeratori che consentono di scorrere facilmente la raccolta. Gli enumeratori vengono utilizzati solo per leggere i dati in una raccolta e non possono essere utilizzati per modificarla.

Alcuni linguaggi di programmazione forniscono un'istruzione che nasconde la complessità legata all'utilizzo diretto di enumeratori. Nelle istruzioni foreach di C#, for each di C++ e For Each di Visual Basic vengono utilizzati enumeratori.

Informazioni sugli enumeratori

L'enumeratore appiattisce una raccolta in modo che si possa accedere ai membri in modo sequenziale. Classi Collection differenti possono avere sequenze differenti. Un enumeratore per un oggetto ArrayList, ad esempio, mantiene l'ordine di inserimento degli elementi nella raccolta, mentre un enumeratore per un oggetto Hashtable visualizza gli elementi in base al relativo codice hash.

Ogni enumeratore si basa sull'interfaccia IEnumerator o sull'interfaccia generica IEnumerator<T>, che richiede i seguenti membri:

  • La proprietà Current fa riferimento al membro corrente nella raccolta.

  • La proprietà MoveNext sposta l'enumeratore verso il membro successivo nella raccolta.

  • La proprietà Reset riporta l'enumeratore all'inizio della raccolta. Current è posizionato prima del primo elemento. Reset non è disponibile nell'interfaccia IEnumerator<T> generica.

Funzionamento dell'enumeratore

Inizialmente, l'enumeratore è posizionato prima del primo elemento della raccolta. Reset riporta inoltre l'enumeratore in questa posizione. In questa posizione la proprietà Current non è definita. È pertanto necessario chiamare MoveNext per spostare l'enumeratore in corrispondenza del primo elemento della raccolta prima di leggere il valore di Current.

Current restituisce lo stesso oggetto fino alla chiamata di MoveNext o Reset. MoveNext imposta Current sull'elemento successivo.

Se MoveNext raggiunge la fine della raccolta, l'enumeratore viene posizionato dopo l'ultimo elemento della raccolta e MoveNext restituisce false. Quando l'enumeratore si trova in questa posizione, anche le successive chiamate a MoveNext restituiranno false. Se l'ultima chiamata a MoveNext restituisce false, la proprietà Current non è definita.

Nelle raccolte non generiche è possibile chiamare Reset seguito da MoveNext per riportare l'enumeratore all'inizio della raccolta.

Nelle raccolte generiche non è possibile impostare nuovamente Current sul primo elemento della raccolta. È necessario creare una nuova istanza di enumeratore.

Un enumeratore rimane valido fino a quando la raccolta rimane invariata. Se vengono apportate modifiche alla raccolta, ad esempio l'aggiunta, la modifica o l'eliminazione di elementi, l'enumeratore verrà irrimediabilmente invalidato e il relativo comportamento sarà non definito.

L'enumeratore non dispone di accesso esclusivo alla raccolta, pertanto il processo di enumerazione di una raccolta non è di per sé thread-safe. Per garantire che l'enumerazione sia thread-safe, è possibile bloccare la raccolta durante l'intera enumerazione. Per consentire l'accesso alla raccolta da parte di più thread per la lettura e la scrittura, è necessario implementare una sincronizzazione personalizzata o utilizzare una delle classi di raccolte thread-safe nello spazio dei nomi System.Collections.Concurrent. Le classi System.Collections.Concurrent.ConcurrentQueue<T> e System.Collections.Concurrent.ConcurrentStack<T> creano uno snapshot degli elementi prima di enumerarli, per impedire che la raccolta venga modificata in un altro thread. La classe System.Collections.Concurrent.ConcurrentDictionary<TKey, TValue> non crea uno snapshot.

La classe System.Collections.Concurrent.BlockingCollection<T> fornisce un metodo enumeratore chiamato GetConsumingEnumerable che modifica la raccolta rimuovendo gli elementi dallo stesso mano a mano che vengono enumerati.

Vedere anche

Riferimenti

IEnumerator

IEnumerator<T>

IDictionaryEnumerator

IEnumerable

IEnumerable<T>

Altre risorse

Creazione e modifica delle raccolte

Raccolte thread-safe