Condividi tramite


Istruzione For Each...Next (Visual Basic)

Aggiornamento: Luglio 2008

Consentono di ripetere un gruppo di istruzioni per ciascun elemento di un insieme.

For Each element [ As datatype ] In group
    [ statements ]
    [ Exit For ]
    [ statements ]
Next [ element ]

Parti

  • element
    Obbligatorio nell'istruzione For Each. Facoltativo nell'istruzione Next. Variabile. Utilizzata per eseguire un'iterazione degli elementi dell'insieme.

  • datatype
    Obbligatoria se element non è già dichiarato. Tipo di dati di element.

  • group
    Obbligatorio. Variabile oggetto. Fa riferimento all'insieme sul quale devono essere ripetute le statements.

  • statements
    Facoltativo. Una o più istruzioni tra For Each e Next che vengono eseguite su ciascun elemento incluso in group.

  • Exit For
    Facoltativo. Trasferisce il controllo all'esterno del ciclo For Each.

  • Next
    Obbligatorio. Termina la definizione del ciclo For Each.

Note

Utilizzare un ciclo For Each...Next quando si desidera ripetere un set di istruzioni per ciascun elemento di un insieme o di una matrice.

Con l'istruzione Istruzione For...Next (Visual Basic) è consigliabile associare ciascuna iterazione di un ciclo a una variabile di controllo e definire i valori iniziale e finale di tale variabile. Con un insieme, invece, non è necessario specificare i valori iniziale e finale e nemmeno conoscere il numero di elementi disponibili. In questo caso, è consigliabile utilizzare un ciclo For Each...Next.

Regole

  • Tipi di dati. Per element è necessario specificare un tipo di dati in cui possa essere convertito il tipo di dati degli elementi di group.

    Il tipo di dati di group deve corrispondere a un tipo di riferimento che punta a un insieme o a una matrice. Di conseguenza, group deve fare riferimento a un oggetto che implementa l'interfaccia IEnumerable dello spazio dei nomi System.Collections oppure l'interfaccia IEnumerable<T> dello spazio dei nomi System.Collections.Generic. IEnumerable definisce il metodo GetEnumerator, il quale restituisce un oggetto enumeratore per l'insieme. L'oggetto enumeratore implementa l'interfaccia IEnumerator dello spazio dei nomi System.Collections ed espone la proprietà Current e i metodi Reset e MoveNext che verranno utilizzati per scorrere l'insieme.

    Gli elementi di group sono generalmente di tipo Object, tuttavia possono essere disponibili anche tipi di dati runtime.

  • Conversioni verso tipi di dati più piccoli. Quando l'oggetto Option Strict viene impostato su On, le conversioni verso un tipo di dati più piccolo causano solitamente errori del compilatore. Nell'esempio seguente, l'assegnazione di m come valore iniziale per n non consente di compilare con l'oggetto Option Strict attivo poiché la conversione di un oggetto Long in un oggetto Integer è una conversione verso un tipo di dati più piccolo.

    Dim m As Long = 987
    ' Does not compile.
    'Dim n As Integer = m
    

    Tuttavia, le conversioni dagli elementi nell'oggetto group all'oggetto element vengono valutate ed eseguite in fase di esecuzione e l'errore di conversione verso un tipo di dati più piccolo viene eliminato. Nell'esempio seguente, nel ciclo For Each non viene segnalato nessun errore del compilatore, anche se viene richiesta la stessa conversione dall'oggetto Long all'oggetto Integer che ha causato un errore nell'esempio precedente.

    Option Strict On
    Module Module1
        Sub Main()
    
            ' The assignment of m to n causes a compiler error when 
            ' Option Strict is on.
            Dim m As Long = 987
            'Dim n As Integer = m
    
            ' The For Each loop requires the same conversion, but
            ' causes no errors. The output is 45 3 987.
            For Each p As Integer In New Long() {45, 3, 987}
                Console.Write(p & " ")
            Next
            Console.WriteLine()
        End Sub
    End Module
    
    

    La mancanza di un errore del compilatore non annulla il rischio di un errore di runtime. Nell'esempio seguente, non viene segnalato alcun errore del compilatore, tuttavia si verifica un errore di runtime quando l'oggetto ToInteger viene applicato a 9876543210. L'errore di runtime si verifica a prescindere dall'attivazione dell'oggetto Option Strict.

    Option Strict On
    
    Module Module1
        Sub Main()
    
            ' The assignment of m to n causes a compiler error when 
            ' Option Strict is on.
            Dim m As Long = 9876543210
            'Dim n As Integer = m
    
            Try
                ' The For Each loop requires the same conversion, but
                ' is not flagged by the compiler. A run-time error is 
                ' raised because 9876543210 is too large for type Integer.
                For Each p As Integer In New Long() {45, 3, 9876543210}
                    Console.Write(p & " ")
                Next
                Console.WriteLine()
            Catch e As System.OverflowException
                Console.WriteLine()
                Console.WriteLine(e.Message)
            End Try
        End Sub
    End Module
    
    
  • Dichiarazione. Se element non è stato dichiarato al di fuori del ciclo, è necessario dichiararlo nell'istruzione For Each. È possibile dichiarare in modo esplicito il tipo dell'oggetto element tramite un'istruzione As oppure è possibile basarsi sull'inferenza dei tipi per assegnare il tipo. In entrambi i casi, l'ambito dell'oggetto element è il corpo del ciclo. Non è tuttavia possibile dichiarare element all'interno e all'esterno del ciclo.

  • Numero di iterazioni. In Visual Basic l'insieme viene restituito solo un volta, ovvero prima dell'inizio del ciclo. Se nel blocco di istruzioni element o group cambiano, le modifiche non avranno alcun effetto sulla ripetizione del ciclo.

  • Cicli nidificati. È possibile nidificare i cicli For Each inserendo un ciclo all'interno di un altro ma dotando ciascuno di essi di una variabile element univoca.

    È inoltre possibile nidificare diversi tipi di strutture di controllo una all'interno dell'altra. Per ulteriori informazioni, vedere Strutture di controllo nidificate.

    Nota:

    Se viene rilevata un'istruzione Next di un livello di nidificazione esterno prima che di un livello interno, il compilatore restituisce un errore. Tuttavia, il compilatore può rilevare questo errore di sovrapposizione solo se si specifica element in ogni istruzione Next.

  • **Identificazione della variabile di controllo.**Se lo si desidera, è possibile specificare element nell'istruzione Next Ciò consente di migliorare la leggibilità del programma, soprattutto se i cicli For Each sono nidificati. È necessario specificare la stessa variabile presente nell'istruzione For Each corrispondente.

  • Trasferimento all'esterno del ciclo. L'Istruzione Exit (Visual Basic) trasferisce immediatamente il controllo all'istruzione che segue l'istruzione Next. È possibile uscire da un ciclo se si rileva una condizione che rende inutile o impossibile continuare a scorrere, quale un valore erroneo o una richiesta di interruzione. Inoltre, se viene intercettata un'eccezione in un'istruzione Try...Catch...Finally, è possibile utilizzare Exit For alla fine del blocco Finally.

    È possibile inserire un numero qualsiasi di istruzioni Exit For nella posizione desiderata all'interno del ciclo For Each. L'istruzione Exit For viene spesso utilizzata dopo la restituzione di alcune condizioni, ad esempio in una struttura If...Then...Else.

  • Cicli senza termine. Uno degli utilizzi di Exit For consiste nella verifica di una condizione che potrebbe provocare un ciclo senza termine, vale a dire un ciclo che potrebbe essere eseguito un numero di volte estremamente grande o infinito. Se si rileva una simile condizione, è possibile utilizzare Exit For per interrompere l'esecuzione del ciclo. Per ulteriori informazioni, vedere Istruzione Do...Loop (Visual Basic).

Comportamento

  • Dall'esecuzione di un ciclo. All'avvio dell'esecuzione del ciclo For Each...Next, viene verificato che group faccia riferimento a un oggetto Collection valido. In caso negativo, verrà generata un'eccezione. In caso affermativo, vengono chiamati il metodo MoveNext e la proprietà Current dell'oggetto enumeratore per restituire il primo elemento. Se il metodo MoveNext indica che non sono disponibili altri elementi, vale a dire che l'insieme è vuoto, il ciclo For Each terminerà e il controllo passa all'istruzione successiva a Next. Altrimenti, element viene impostato sul primo elemento, quindi viene eseguito il blocco di istruzioni.

  • Iterazioni del ciclo. Ogni volta che viene rilevata l'istruzione Next, si ritorna all'istruzione For Each. Vengono chiamati di nuovo il metodo MoveNext e la proprietà Current per restituire l'elemento successivo, quindi, in base al risultato, viene eseguito il blocco oppure viene terminato il ciclo. Questo processo continua finché il metodo MoveNext indica che non esistono altri elementi oppure finché non viene rilevata un'istruzione Exit For.

  • **Terminazione del ciclo.**Dopo che tutti gli elementi dell'insieme sono stati assegnati a element, il ciclo For Each termina e il controllo passa all'istruzione successiva all'istruzione Next.

  • Modifica dei valori di un'iterazione. Se si modifica il valore dell'argomento element durante un ciclo, le operazioni di lettura e debug del codice potrebbero risultare più difficili. La modifica del valore del parametro group non ha impatto sull'insieme e sui relativi elementi, i quali sono stati definiti quando il ciclo è stato avviato per la prima volta.

  • Ordine di scorrimento. Quando si esegue un ciclo For Each...Next, lo scorrimento dell'insieme è controllato dall'oggetto enumeratore restituito dal metodo GetEnumerator. L'ordine di scorrimento quindi non è determinato da Visual Basic, ma dal metodo MoveNext dell'oggetto enumeratore. Ciò significa che non è possibile prevedere quale elemento dell'insieme verrà restituito per primo in element o quale sarà il successivo ad essere restituito dopo un determinato elemento.

    Se è previsto un ordine di scorrimento dell'insieme particolare, è sconsigliabile utilizzare un ciclo For Each...Next, a meno che non si conoscano le caratteristiche dell'oggetto enumeratore esposto dall'insieme. È possibile ottenere risultati più affidabili utilizzando un'altra struttura di ciclo, quale For...Nexto Do...Loop.

  • Modifica dell'insieme. L'oggetto enumeratore restituito da GetEnumerator non consente in genere di modificare l'insieme mediante l'aggiunta, l'eliminazione, la sostituzione o il riordino di elementi. Se si modifica l'insieme dopo aver iniziato un ciclo For Each...Next, l'oggetto enumeratore diventa non valido e il tentativo successivo di accedere a un elemento produce un'eccezione InvalidOperationException.

    Tuttavia, il blocco delle modifiche non è determinato da Visual Basic, ma piuttosto dall'implementazione dell'interfaccia IEnumerable. È possibile implementare IEnumerable in modo da consentire le modifiche durante l'iterazione. Se si intende procedere a tale modifica dinamica, accertarsi di avere un'adeguata conoscenza delle caratteristiche dell'implementazione di IEnumerable nell'insieme utilizzato.

  • Modifica degli elementi di un insieme. La proprietà Current dell'oggetto enumeratore è ReadOnly (Visual Basic) e restituisce una copia locale di ogni elemento dell'insieme. Pertanto non sarà possibile modificare gli elementi stessi in un ciclo For Each...Next. Le eventuali modifiche apportate influenzano solo la copia locale di Current e non si riflettono nell'insieme sottostante. Se tuttavia un elemento è un tipo di riferimento, sarà possibile modificare i membri dell'istanza a cui esso punta. Questa condizione è illustrata nell'esempio che segue.

    Sub lightBlueBackground(ByVal thisForm As System.Windows.Forms.Form)
        For Each thisControl As System.Windows.Forms.Control In thisForm.Controls
            thisControl.BackColor = System.Drawing.Color.LightBlue
        Next thisControl
    End Sub
    

    Nell'esempio precedente è possibile modificare il membro BackColor di ciascun elemento thisControl ma non è possibile modificare l'elemento thisControl stesso.

  • Attraversamento di matrici. Dal momento che la classe Array implementa l'interfaccia IEnumerable, tutte le matrici espongono il metodo GetEnumerator. Pertanto è possibile scorrere una matrice con un ciclo For Each...Next. Tuttavia gli elementi della matrice possono essere solo letti, ma non modificati. Per informazioni generali, vedere Procedura: eseguire diverse istruzioni per ciascun elemento in un insieme o matrice.

Esempio

Nell'esempio seguente viene utilizzata l'istruzione For Each...Next per cercare la stringa "Hello" in tutti gli elementi di un insieme. Nell'esempio si presume che l'insieme thisCollection sia già stato creato e che i relativi elementi siano di tipo String.

Dim found As Boolean = False
Dim thisCollection As New Collection
For Each thisObject As String In thisCollection
    If thisObject = "Hello" Then
        found = True
        Exit For
    End If
Next thisObject

Vedere anche

Attività

Procedura: eseguire diverse istruzioni per ciascun elemento in un insieme o matrice

Procedura: migliorare le prestazioni di un ciclo

Concetti

Strutture di ciclo

Insiemi in Visual Basic

Conversioni di ampliamento e restrizione

Riferimenti

Istruzione While...End While (Visual Basic)

Istruzione Do...Loop (Visual Basic)

Cronologia delle modifiche

Date

History

Motivo

Luglio 2008

Aggiunta sezione sulle conversioni verso un tipo di dati più piccolo.

Commenti e suggerimenti dei clienti.