For Each...Next-Anweisung (Visual Basic)

Wiederholt eine Gruppe von Anweisungen für jedes Element in einer Auflistung.

Syntax

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

Bestandteile

Begriff Definition
element Erforderlich in der For Each Anweisung. Optional in der Next Anweisung. Variable Wird verwendet, um die Elemente der Auflistung zu durchlaufen.
datatype Optional, wenn Option Infer aktiviert (standard) oder element bereits deklariert ist; erforderlich, wenn Option Infer sie deaktiviert ist und element noch nicht deklariert ist. Der Datentyp von element.
group Erforderlich. Eine Variable mit einem Typ, der ein Auflistungstyp oder Objekt ist. Bezieht sich auf die Auflistung, über die die statements wiederholt werden soll.
statements Optional. Mindestens eine Anweisung zwischen For Each und Next die für jedes Element in group.
Continue For Optional. Überträgt das Steuerelement an den Anfang der For Each Schleife.
Exit For Optional. Überträgt die Kontrolle über die For Each Schleife.
Next Erforderlich. Beendet die Definition der For Each Schleife.

Einfaches Beispiel

Verwenden Sie eine For Each...Next -Schleife, wenn Sie eine Reihe von Anweisungen für jedes Element einer Auflistung oder eines Arrays wiederholen möchten.

Tipp

A for... Die nächste Anweisung funktioniert gut, wenn Sie jede Iteration einer Schleife einer Steuerelementvariable zuordnen und die Anfangs- und Endwerte der Variablen bestimmen können. Wenn Sie jedoch mit einer Sammlung umgehen, ist das Konzept der anfänglichen und endgültigen Werte nicht sinnvoll, und Sie wissen nicht unbedingt, wie viele Elemente die Sammlung hat. In diesem Fall ist eine For Each...Next -Schleife oft eine bessere Wahl.

Im folgenden Beispiel wird der For Each...Next anweisung durchläuft alle Elemente einer List-Auflistung.

' Create a list of strings by using a
' collection initializer.
Dim lst As New List(Of String) _
    From {"abc", "def", "ghi"}

' Iterate through the list.
For Each item As String In lst
    Debug.Write(item & " ")
Next
Debug.WriteLine("")
'Output: abc def ghi

Weitere Beispiele finden Sie unter Sammlungen und Arrays.

Nested Loops

Sie können Schleifen verschachteln For Each , indem Sie eine Schleife innerhalb einer anderen Schleife einfügen.

Das folgende Beispiel veranschaulicht geschachtelte For Each...Next Strukturen.

' Create lists of numbers and letters
' by using array initializers.
Dim numbers() As Integer = {1, 4, 7}
Dim letters() As String = {"a", "b", "c"}

' Iterate through the list by using nested loops.
For Each number As Integer In numbers
    For Each letter As String In letters
        Debug.Write(number.ToString & letter & " ")
    Next
Next
Debug.WriteLine("")
'Output: 1a 1b 1c 4a 4b 4c 7a 7b 7c

Wenn Sie Schleifen verschachteln, muss jede Schleife eine eindeutige element Variable aufweisen.

Sie können auch unterschiedliche Arten von Kontrollstrukturen ineinander verschachteln. Weitere Informationen finden Sie unter geschachtelte Steuerelementstrukturen.

Beenden für und Fortfahren für

Die Exit For-Anweisung bewirkt, dass die Ausführung die For...Next loop and transfer control to the statement that follows the Next statement.

Die Continue For Anweisung überträgt die Steuerung sofort an die nächste Iteration der Schleife. Weitere Informationen finden Sie unter "Continue-Anweisung".

Im folgenden Beispiel wird gezeigt, wie die Continue For Anweisungen verwendet werden Exit For .

Dim numberSeq() As Integer =
    {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}

For Each number As Integer In numberSeq
    ' If number is between 5 and 8, continue
    ' with the next iteration.
    If number >= 5 And number <= 8 Then
        Continue For
    End If

    ' Display the number.
    Debug.Write(number.ToString & " ")

    ' If number is 10, exit the loop.
    If number = 10 Then
        Exit For
    End If
Next
Debug.WriteLine("")
' Output: 1 2 3 4 9 10

Sie können eine beliebige Anzahl von Exit For Anweisungen in eine For Each Schleife einfügen. Wenn sie in geschachtelten For Each Schleifen verwendet werden, Exit For führt die Ausführung zum Beenden der innersten Schleife und überträgt die Steuerung auf die nächste höhere Schachtelungsebene.

Exit For wird häufig nach einer Auswertung einiger Bedingungen verwendet, z. B. in einem If...Then ...Else Struktur. Möglicherweise möchten Sie für die folgenden Bedingungen verwenden Exit For :

  • Die Fortsetzung des Kursierens ist unnötig oder unmöglich. Dies kann durch einen fehlerhaften Wert oder eine Beendigungsanforderung verursacht werden.

  • Eine Ausnahme wird in einem Try...Catch ...Finally. Möglicherweise verwenden Exit For Sie am Ende des Finally Blocks.

  • Es gibt eine Endlosschleife, die eine Schleife ist, die eine große oder sogar unendliche Anzahl von Zeiten ausführen kann. Wenn Sie eine solche Bedingung erkennen, können Exit For Sie die Schleife escapen. Weitere Informationen finden Sie unter Do... Loop Anweisung.

Iterators

Sie verwenden einen Iterator , um eine benutzerdefinierte Iteration über eine Auflistung auszuführen. Ein Iterator kann eine Funktion oder ein Get Accessor sein. Es verwendet eine Yield Anweisung, um jedes Element der Auflistung jeweils einzeln zurückzugeben.

Sie rufen einen Iterator mithilfe einer For Each...Next Anweisung auf. Jede Iteration der For Each-Schleife ruft den Iterator auf. Wenn eine Yield Anweisung im Iterator erreicht wird, wird der Ausdruck in der Yield Anweisung zurückgegeben, und der aktuelle Speicherort im Code wird beibehalten. Wenn der Iterator das nächste Mal aufgerufen wird, wird die Ausführung von dieser Position neu gestartet.

Im folgenden Beispiel wird eine Iteratorfunktion verwendet. Die Iteratorfunktion weist eine Anweisung auf Yield , die sich in einer For... Nächste Schleife. In der ListEvenNumbers Methode erstellt jede Iteration des For Each Anweisungstexts einen Aufruf der Iteratorfunktion, die mit der nächsten Yield Anweisung fortläuft.

Public Sub ListEvenNumbers()
    For Each number As Integer In EvenSequence(5, 18)
        Debug.Write(number & " ")
    Next
    Debug.WriteLine("")
    ' Output: 6 8 10 12 14 16 18
End Sub

Private Iterator Function EvenSequence(
ByVal firstNumber As Integer, ByVal lastNumber As Integer) _
As System.Collections.Generic.IEnumerable(Of Integer)

    ' Yield even numbers in the range.
    For number = firstNumber To lastNumber
        If number Mod 2 = 0 Then
            Yield number
        End If
    Next
End Function

Weitere Informationen finden Sie unter Iterators, Yield Statement und Iterator.

Technische Implementierung

Wenn ein For Each...NextDie Anweisung wird ausgeführt, Visual Basic die Auflistung nur einmal auswertet, bevor die Schleife gestartet wird. Wenn sich ihre Anweisung blockiert element oder groupdiese Änderungen nicht auf die Iteration der Schleife auswirken.

Wenn alle Elemente in der Auflistung nacheinander zugewiesen elementwurden, wird die For Each Schleife beendet und das Steuerelement an die Anweisung nach der Next Anweisung übergeben.

Wenn Option Infer aktiviert ist (standardeinstellung), kann der Visual Basic Compiler den Datentyp von element. Wenn sie deaktiviert ist und element nicht außerhalb der Schleife deklariert wurde, müssen Sie sie in der For Each Anweisung deklarieren. Verwenden Sie eine As Klausel, um den Datentyp explizit element zu deklarieren. Es sei denn, der Datentyp des Elements wird außerhalb des For Each...Next -Konstrukts definiert, sein Bereich ist der Textkörper der Schleife. Beachten Sie, dass Sie nicht sowohl außerhalb als auch innerhalb der Schleife deklarieren element können.

Sie können optional in der Next Anweisung angebenelement. Dadurch wird die Lesbarkeit Ihres Programms verbessert, insbesondere, wenn Sie geschachtelte For Each Schleifen haben. Sie müssen dieselbe Variable wie die variable angeben, die in der entsprechenden For Each Anweisung angezeigt wird.

Möglicherweise möchten Sie vermeiden, den Wert einer element Schleife zu ändern. Dadurch kann es schwieriger sein, Ihren Code zu lesen und zu debuggen. Das Ändern des Werts wirkt group sich nicht auf die Auflistung oder deren Elemente aus, die bestimmt wurden, wenn die Schleife zuerst eingegeben wurde.

Wenn Sie Schleifen verschachteln, wenn eine Next Anweisung einer äußeren Schachtelungsebene vor der Next inneren Ebene auftritt, signalisiert der Compiler einen Fehler. Der Compiler kann diesen überlappenden Fehler jedoch nur erkennen, wenn Sie in jeder Next Anweisung angebenelement.

Wenn Ihr Code von der Durchquerung einer Auflistung in einer bestimmten Reihenfolge abhängt, ist eine For Each...Next -Schleife nicht die beste Wahl, es sei denn, Sie wissen die Merkmale des Aufzählungsobjekts, das die Auflistung verfügbar macht. Die Reihenfolge der Traversal wird nicht durch Visual Basic bestimmt, sondern durch die MoveNext Methode des Enumeratorobjekts. Daher können Sie möglicherweise nicht voraussagen, in welchem Element der Auflistung das erste zurückgegeben werden elementsoll, oder welches das nächste element nach einem bestimmten Element zurückgegeben werden soll. Sie können zuverlässigere Ergebnisse mithilfe einer anderen Schleifenstruktur wie ... ForNext oder Do...Looperzielen.

Die Laufzeit muss in der Lage sein, die Elemente in group .element Die [Option Strict] -Anweisung steuert, ob sowohl Verbreiterung als auch Schmaler Konvertierungen zulässig sind (Option Strict ist deaktiviert, der Standardwert) oder ob nur Erweiterungskonvertierungen zulässig sind (Option Strict ist aktiviert). Weitere Informationen finden Sie unter "Schmale Konvertierungen".

Der Datentyp muss group ein Verweistyp sein, der sich auf eine Auflistung oder ein Array bezieht, das aufgezählt werden kann. Dies bedeutet am häufigsten, dass es sich um ein Objekt bezieht, group das die IEnumerable Schnittstelle des System.Collections Namespaces oder die IEnumerable<T> Schnittstelle des System.Collections.Generic Namespace implementiert. System.Collections.IEnumerable definiert die GetEnumerator Methode, die ein Enumerationeratorobjekt für die Auflistung zurückgibt. Das Enumerationsobjekt implementiert die System.Collections.IEnumerator Schnittstelle des System.Collections Namespaces und macht die Eigenschaft und die CurrentResetMoveNext Methoden verfügbar. Visual Basic verwendet diese, um die Sammlung zu durchlaufen.

Eingrenzungskonvertierungen

Wenn Option Strict festgelegt Onist, führt das Einschränken von Konvertierungen ordinariell zu Compilerfehlern. In einer For Each Anweisung werden jedoch Konvertierungen aus den Elementen groupelement in die Laufzeit ausgewertet und ausgeführt, und Compilerfehler, die durch schmale Konvertierungen verursacht werden, werden unterdrückt.

Im folgenden Beispiel wird die Zuordnung m als Anfangswert n nicht kompiliert, wenn Option Strict sie aktiviert ist, da die Konvertierung einer Long zu einer Integer schmalen Konvertierung entspricht. In der For Each Anweisung wird jedoch kein Compilerfehler gemeldet, auch wenn die Zuordnung number dieselbe Konvertierung von Long zu Integererfordert. In der Anweisung, die For Each eine große Zahl enthält, tritt ein Laufzeitfehler auf, wenn ToInteger auf die große Zahl angewendet wird.

Option Strict On

Imports System

Module Program
    Sub Main(args As String())
        ' 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, even when Option Strict is on.
        For Each number As Integer In New Long() {45, 3, 987}
            Console.Write(number & " ")
        Next
        Console.WriteLine()
        ' Output: 45 3 987

        ' Here a run-time error is raised because 9876543210
        ' is too large for type Integer.
        'For Each number As Integer In New Long() {45, 3, 9876543210}
        '    Console.Write(number & " ")
        'Next
    End Sub
End Module

IEnumerator-Aufrufe

Wenn die Ausführung einer For Each...Next -Schleife gestartet wird, überprüft Visual Basic, dass group sich auf ein gültiges Auflistungsobjekt bezieht. Wenn nicht, wird eine Ausnahme ausgelöst. Andernfalls ruft sie die MoveNext Methode und die Current Eigenschaft des Aufzählungsobjekts auf, um das erste Element zurückzugeben. Wenn MoveNext angegeben wird, dass kein nächstes Element vorhanden ist, das heißt, wenn die Auflistung leer ist, wird die For Each Schleife beendet und das Steuerelement an die Anweisung nach der Next Anweisung übergeben. Andernfalls wird Visual Basic auf das erste Element festgelegt element und der Anweisungsblock ausgeführt.

Jedes Mal, wenn Visual Basic auf die Next Anweisung trifft, wird sie an die For Each Anweisung zurückgegeben. Es wird erneut aufgerufen MoveNext und Current das nächste Element zurückgegeben, und es wird entweder der Block ausgeführt oder die Schleife abhängig vom Ergebnis beendet. Dieser Prozess wird fortgesetzt, bis MoveNext angegeben wird, dass kein nächstes Element vorhanden ist oder eine Exit For Anweisung aufgetreten ist.

Ändern der Auflistung. Das von der Regel zurückgegebene GetEnumerator Enumerationsobjekt ermöglicht es Ihnen nicht, die Auflistung zu ändern, indem Sie Elemente hinzufügen, löschen, ersetzen oder neu anordnen. Wenn Sie die Auflistung ändern, nachdem Sie eine For Each...Next -Schleife initiiert haben, wird das Enumerationeratorobjekt ungültig, und der nächste Versuch, auf ein Element zuzugreifen, verursacht eine InvalidOperationException Ausnahme.

Diese Sperrung der Änderung wird jedoch nicht durch Visual Basic, sondern durch die Implementierung der IEnumerable Schnittstelle bestimmt. Es ist möglich, in einer Weise zu implementieren IEnumerable , die änderungen während der Iteration ermöglicht. Wenn Sie eine solche dynamische Änderung in Betracht ziehen, stellen Sie sicher, dass Sie die Merkmale der Implementierung für die IEnumerable von Ihnen verwendete Sammlung verstehen.

Ändern von Auflistungselementen. Die Current Eigenschaft des Enumeratorobjekts ist ReadOnly, und es gibt eine lokale Kopie der einzelnen Auflistungselemente zurück. Dies bedeutet, dass Sie die Elemente selbst in einer For Each...Next -Schleife nicht ändern können. Alle Änderungen, die Sie vornehmen, wirken sich nur auf die lokale Kopie aus Current und werden nicht wieder in die zugrunde liegende Auflistung wiedergegeben. Wenn ein Element jedoch ein Verweistyp ist, können Sie die Member der Instanz ändern, auf die es verweist. Im folgenden Beispiel wird das BackColor Element jedes thisControl Elements geändert. Sie können sich jedoch nicht selbst ändern thisControl .

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

Im vorherigen Beispiel kann das BackColor Element jedes thisControl Elements geändert werden, obwohl es sich nicht selbst ändern thisControl kann.

Durchlaufen von Arrays. Da die Array Klasse die IEnumerable Schnittstelle implementiert, machen alle Arrays die GetEnumerator Methode verfügbar. Dies bedeutet, dass Sie ein Array mit einer For Each... -Next Schleife durchlaufen können. Sie können jedoch nur die Arrayelemente lesen. Sie können sie nicht ändern.

Beispiel 1

Im folgenden Beispiel werden alle Ordner in C:\ aufgeführt. verzeichnis mithilfe der DirectoryInfo Klasse.

Dim dInfo As New System.IO.DirectoryInfo("c:\")
For Each dir As System.IO.DirectoryInfo In dInfo.GetDirectories()
    Debug.WriteLine(dir.Name)
Next

Beispiel 2

Das folgende Beispiel zeigt ein Verfahren zum Sortieren einer Auflistung. Im Beispiel werden Instanzen einer Car Klasse sortiert, die in einer List<T>. Die Car-Klasse implementiert die IComparable<T>-Schnittstelle, die die Implementierung der CompareTo-Methode erfordert.

Jeder Aufruf der Methode führt einen einzelnen Vergleich aus, der für die CompareTo Sortierung verwendet wird. Vom Benutzer erstellter Code in der CompareTo-Methode gibt einen Wert für jeden Vergleich des aktuellen Objekts mit einem anderen Objekt zurück. Der zurückgegebene Wert ist kleiner als Null, wenn das aktuelle Objekt kleiner ist als das andere Objekt, größer als Null, wenn das aktuelle Objekt größer als das andere Objekt ist und Null, wenn beide Objekt gleich groß sind. Dies ermöglicht es Ihnen, in dem Code die Kriterien für größer als, kleiner als und gleich zu definieren.

In der ListCars-Methode sortiert die cars.Sort()-Anweisung die Liste. Dieser Aufruf der Sort-Methode von List<T> führt dazu, dass die CompareTo-Methode für die Car-Objekte in der List automatisch aufgerufen wird.

Public Sub ListCars()

    ' Create some new cars.
    Dim cars As New List(Of Car) From
    {
        New Car With {.Name = "car1", .Color = "blue", .Speed = 20},
        New Car With {.Name = "car2", .Color = "red", .Speed = 50},
        New Car With {.Name = "car3", .Color = "green", .Speed = 10},
        New Car With {.Name = "car4", .Color = "blue", .Speed = 50},
        New Car With {.Name = "car5", .Color = "blue", .Speed = 30},
        New Car With {.Name = "car6", .Color = "red", .Speed = 60},
        New Car With {.Name = "car7", .Color = "green", .Speed = 50}
    }

    ' Sort the cars by color alphabetically, and then by speed
    ' in descending order.
    cars.Sort()

    ' View all of the cars.
    For Each thisCar As Car In cars
        Debug.Write(thisCar.Color.PadRight(5) & " ")
        Debug.Write(thisCar.Speed.ToString & " ")
        Debug.Write(thisCar.Name)
        Debug.WriteLine("")
    Next

    ' Output:
    '  blue  50 car4
    '  blue  30 car5
    '  blue  20 car1
    '  green 50 car7
    '  green 10 car3
    '  red   60 car6
    '  red   50 car2
End Sub

Public Class Car
    Implements IComparable(Of Car)

    Public Property Name As String
    Public Property Speed As Integer
    Public Property Color As String

    Public Function CompareTo(ByVal other As Car) As Integer _
        Implements System.IComparable(Of Car).CompareTo
        ' A call to this method makes a single comparison that is
        ' used for sorting.

        ' Determine the relative order of the objects being compared.
        ' Sort by color alphabetically, and then by speed in
        ' descending order.

        ' Compare the colors.
        Dim compare As Integer
        compare = String.Compare(Me.Color, other.Color, True)

        ' If the colors are the same, compare the speeds.
        If compare = 0 Then
            compare = Me.Speed.CompareTo(other.Speed)

            ' Use descending order for speed.
            compare = -compare
        End If

        Return compare
    End Function
End Class

Weitere Informationen