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 In der -Anweisung For Each erforderlich. Optional in der Next -Anweisung. Variable Wird verwendet, um die Elemente der Auflistung zu iterieren.
datatype Optional, Option Infer wenn aktiviert ist (Standardeinstellung) oder bereits deklariert ist; erforderlich, wenn deaktiviert ist und element noch nicht deklariert Option Infer element ist. Der Datentyp von element.
group Erforderlich. Eine Variable mit einem Typ, der ein Auflistungstyp oder ein Objekt ist. Bezieht sich auf die Auflistung, über statements die wiederholt werden soll.
statements Optional. Mindestens eine -Anweisung zwischen For Each und , die für jedes Element in ausgeführt Next group wird.
Continue For Optional. Überträgt die Steuerung an den Anfang der For Each Schleife.
Exit For Optional. Überträgt die Steuerung aus der For Each Schleife.
Next Erforderlich. Beendet die Definition der For Each Schleife.

Einfaches Beispiel

Verwenden Sie eine ... -Schleife, wenn Sie einen Satz For Each Next 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 Steuerelementvariablen zuordnen und die anfänglichen und endgültigen Werte dieser Variablen bestimmen können. Wenn Sie sich jedoch mit einer Sammlung beschäftigen, ist das Konzept der anfänglichen und endgültigen Werte nicht sinnvoll, und Sie wissen nicht unbedingt, wie viele Elemente die Sammlung enthält. In diesem Fall ist eine For Each ... Next -Schleife häufig die bessere Wahl.

Im folgenden Beispiel wird For Each ...Next -Anweisung durch iteriert 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 For Each Schleifen schachteln, indem Sie eine Schleife in eine andere setzen.

Im folgenden Beispiel wird die 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 schachteln, muss jede Schleife eine eindeutige Variable element haben.

Sie können auch verschiedene Arten von Steuerelementstrukturen ineinander schachteln. Weitere Informationen finden Sie unter Geschachtelte Steuerelementstrukturen.

Beenden für und Fortfahren für

Die Exit For-Anweisung bewirkt, dass die Ausführung ... For``Next -Schleife und überträgt die Steuerung an die -Anweisung, die der -Anweisung Next folgt.

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

Im folgenden Beispiel wird die Verwendung der Anweisungen Continue For und Exit For veranschaulicht.

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 Schleife For Each setzen. Bei Verwendung in geschachtelten Schleifen beendet die Ausführung die innerste Schleife und überträgt die Steuerung auf die nächste For Each Exit For höhere Schachtelungsebene.

Exit For wird häufig nach einer Auswertung einer Bedingung verwendet, z. B. in einem If ... Then ...Else Struktur. Sie sollten für die Exit For folgenden Bedingungen verwenden:

  • Das Weitere Iterieren 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. Sie können Exit For am Ende des Blocks Finally verwenden.

  • Es gibt eine Endlosschleife, bei der es sich um eine Schleife handelt, die sehr oft oder sogar unendlich oft ausgeführt werden kann. Wenn Sie eine solche Bedingung erkennen, können Sie verwenden, Exit For um die Schleife zu escapen. Weitere Informationen finden Sie unter Do... Loop-Anweisung.

Iterators

Sie verwenden einen Iterator, um eine benutzerdefinierte Iteration über eine Auflistung durchzuführen. Ein Iterator kann eine Funktion oder ein Get Accessor sein. Er verwendet eine Yield -Anweisung, um jedes Element der Auflistung nacheinander zurück zu geben.

Sie rufen einen Iterator mithilfe einer -Anweisung For Each...Next auf. Jede Iteration der For Each-Schleife ruft den Iterator auf. Wenn eine Yield -Anweisung im Iterator erreicht wird, wird der Ausdruck in der -Anweisung zurückgegeben, und die aktuelle Yield Position 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 verfügt über eine Yield -Anweisung, die sich in einem For... befindet. Nächste Schleife. In der -Methode erstellt jede Iteration des Anweisungskörpers einen Aufruf der ListEvenNumbers For Each Iteratorfunktion, der zur nächsten Anweisung Yield übergeht.

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 Iteratoren, Yield-Anweisungund Iterator.

Technische Implementierung

Wenn ein For Each ...Next -Anweisung wird Visual Basic die Auflistung nur einmal ausgewertet, bevor die Schleife gestartet wird. Wenn ihre Anweisung änderungen oder ändert, wirken sich diese Änderungen element nicht auf die Iteration der group Schleife aus.

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

Wenn Option Infer auf (die Standardeinstellung) festgelegt ist, Visual Basic Compiler den Datentyp von element abgeleitet. Wenn sie deaktiviert ist und nicht außerhalb der Schleife deklariert wurde, müssen Sie sie element in der -Anweisung For Each deklarieren. Verwenden Sie eine -Klausel, um element den Datentyp von explizit zu As deklarieren. Sofern der Datentyp des Elements nicht außerhalb des ...-Konstrukts definiert ist, ist For Each Next sein Gültigkeitsbereich der Text der Schleife. Beachten Sie, dass Sie nicht sowohl element außerhalb als auch innerhalb der Schleife deklarieren können.

Sie können optional element in der -Anweisung Next angeben. Dies verbessert die Lesbarkeit Des Programms, insbesondere wenn Sie For Each geschachtelte Schleifen haben. Sie müssen die gleiche Variable angeben wie die, die in der entsprechenden -Anweisung For Each angezeigt wird.

Sie sollten vermeiden, den Wert von innerhalb einer element Schleife zu ändern. Dies kann das Lesen und Debuggen Ihres Codes erschweren. Das Ändern des Werts von wirkt sich nicht auf die Auflistung oder deren Elemente aus, die bestimmt group wurden, als die Schleife zum ersten Mal eingegeben wurde.

Wenn beim Schachteln von Schleifen eine Anweisung einer äußeren Schachtelungsebene vor der einer inneren Ebene gefunden wird, signalisiert der Compiler Next Next einen Fehler. Der Compiler kann diesen überlappenden Fehler jedoch nur erkennen, wenn Sie element in jeder Anweisung Next angeben.

Wenn Ihr Code vom Durchlaufen einer Auflistung in einer bestimmten Reihenfolge abhängt, ist eine ... -Schleife nicht die beste Wahl, es sei denn, Sie kennen die Merkmale des For Each Enumeratorobjekts, das die Auflistung verfügbar Next macht. Die Reihenfolge des Durchlaufs wird nicht durch Visual Basic, sondern durch die -Methode des MoveNext Enumeratorobjekts bestimmt. Daher können Sie möglicherweise nicht vorhersagen, welches Element der Auflistung das erste element ist, das in zurückgegeben wird, oder welches das nächste ist, das nach einem bestimmten element Element zurückgegeben wird. Sie können zuverlässigere Ergebnisse erzielen, indem Sie eine andere Schleifenstruktur verwenden, z. B. For ... Next oder ... Do Loop .

Die Runtime muss in der Lage sein, die Elemente in in group zu element konvertieren. Die [ ] -Anweisung steuert, ob sowohl widening- als auch narrowing-Konvertierungen zulässig sind ( ist off, ihr Standardwert) oder ob nur Option Strict widening conversions zulässig sind Option Strict ( Option Strict ist aktiviert). Weitere Informationen finden Sie unter Narrowing conversions (Einengen von Konvertierungen).

Der Datentyp von muss ein Verweistyp sein, der auf eine Auflistung oder ein Array verweist, group das aufzählbar ist. In der Regel bedeutet group dies, dass auf ein Objekt verweist, das die Schnittstelle des Namespace oder der Schnittstelle des Namespace IEnumerable System.Collections IEnumerable<T> System.Collections.Generic implementiert. System.Collections.IEnumerable definiert die GetEnumerator -Methode, die ein Enumeratorobjekt für die Auflistung zurückgibt. Das Enumeratorobjekt implementiert die -Schnittstelle des -Namespace und macht die -Eigenschaft sowie System.Collections.IEnumerator System.Collections die Current -Methode und die Reset MoveNext -Methode verfügbar. Visual Basic verwendet diese, um die Auflistung zu durchlaufen.

Eingrenzungskonvertierungen

Wenn Option Strict auf festgelegt On ist, verursachen einengende Konvertierungen normalerweise Compilerfehler. In einer -Anweisung werden Jedoch Konvertierungen von den Elementen in in zur For Each group Laufzeit ausgewertet und element ausgeführt, und Compilerfehler, die durch einschränkende Konvertierungen verursacht werden, werden unterdrückt.

Im folgenden Beispiel wird die Zuweisung von m als Anfangswert für n nicht kompiliert, wenn ein Option Strict ist, da die Konvertierung von in Long eine eine Integer einschränkende Konvertierung ist. In der For Each -Anweisung wird jedoch kein Compilerfehler gemeldet, obwohl die Zuweisung zu number dieselbe Konvertierung von in Long Integer erfordert. In der For Each -Anweisung, die 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, ob group auf ein gültiges Auflistungsobjekt verweist. Wenn dies nicht der Fall ist, wird eine Ausnahme ausgelöst. Andernfalls ruft sie die MoveNext -Methode und die Current -Eigenschaft des Enumeratorobjekts auf, um das erste Element zurückzugeben. Wenn MoveNext angibt, dass kein nächstes Element vorhanden ist, d. h., wenn die Auflistung leer ist, wird die For Each Schleife beendet, und die Steuerung wird an die Anweisung übergeben, die auf die Next Anweisung folgt. Andernfalls legt Visual Basic auf das erste Element fest element und führt den Anweisungsblock aus.

Jedes Mal, wenn Visual Basic auf die Next Anweisung trifft, kehrt sie zur For Each -Anweisung zurück. Es ruft erneut MoveNext auf und , um das nächste Element Current zurückzugeben, und führt je nach Ergebnis entweder den -Block aus oder beendet die Schleife. Dieser Prozess wird fortgesetzt, bis MoveNext angibt, dass kein nächstes Element vorhanden ist oder eine Exit For -Anweisung gefunden wird.

Ändern der Auflistung. Mit dem von zurückgegebenen Enumeratorobjekt GetEnumerator können Sie die Auflistung normalerweise nicht ändern, indem Sie Elemente hinzufügen, löschen, ersetzen oder neu anordnen. Wenn Sie die Auflistung ändern, nachdem Sie eine ... -Schleife initiiert For Each Next haben, wird das Enumeratorobjekt ungültig, und der nächste Versuch, auf ein Element zuzugreifen, löst eine InvalidOperationException Ausnahme aus.

Diese Blockierung der Änderung wird jedoch nicht durch Visual Basic bestimmt, sondern durch die Implementierung der IEnumerable -Schnittstelle. Es ist möglich, auf eine Weise zu IEnumerable implementieren, 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 IEnumerable die von Ihnen verwendeten Sammlung verstehen.

Ändern von Auflistungselementen. Die Current -Eigenschaft des Enumeratorobjekts ist ReadOnlyund gibt eine lokale Kopie jedes Auflistungselements zurück. Dies bedeutet, dass Sie die Elemente selbst nicht in einer For Each ... Next -Schleife ändern können. Jede Änderung, die Sie vornehmen, wirkt sich nur auf die lokale Kopie von aus Current und wird nicht in der zugrunde liegenden Sammlung widergespiegelt. Wenn ein Element jedoch ein Verweistyp ist, können Sie die Member der Instanz ändern, auf die es verweist. Im folgenden Beispiel wird der BackColor Member jedes thisControl Elements geändert. Sie können sich jedoch nicht thisControl selbst ändern.

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 der Member jedes Elements geändert BackColor thisControl werden, obwohl es sich selbst nicht ä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:\ aufgelistet. directory 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 gespeichert List<T> sind. Die Car-Klasse implementiert die IComparable<T>-Schnittstelle, die die Implementierung der CompareTo-Methode erfordert.

Jeder Aufruf der CompareTo -Methode macht einen einzelnen Vergleich, der zum Sortieren 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

Siehe auch