Freigeben über


Für jeden... 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 For Each-Anweisung erforderlich. 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 deaktiviert 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 Wahlfrei. Mindestens eine Anweisung zwischen For Each und Next die für jedes Element in group.
Continue For Wahlfrei. Überträgt die Steuerung an den Anfang der For Each Schleife.
Exit For Wahlfrei. Überträgt die Steuerung aus dem 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... Next Statement funktioniert gut, wenn Sie jede Iteration einer Schleife einer Steuerelementvariable zuordnen und die Anfangs- und Endwerte dieser Variablen bestimmen können. Wenn Sie sich jedoch mit einer Sammlung befassen, ist das Konzept der Anfangs- und Endwerte nicht aussagekräftig, 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 die 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.

Geschachtelte Schleifen

Sie können For Each-Schleifen schachteln, indem Sie eine Schleife in einer anderen platzieren.

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 über eine eindeutige element Variable verfügen.

Sie können auch verschiedene Arten von Kontrollstrukturen miteinander verschachteln. Weitere Informationen finden Sie unter Geschachtelte Kontrollstrukturen.

Exit For und Continue For

Die Exit For-Anweisung bewirkt, dass die Ausführung die For... Next Überträgt die Steuerung an die Anweisung, die auf die Next Anweisung folgt.

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

Das folgende Beispiel zeigt, wie die Continue For Und-Anweisungen Exit For verwendet werden.

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 wird, Exit For beendet die Ausführung die innerste Schleife und überträgt die Steuerung auf die nächste höhere Ebene der Schachtelung.

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

  • Die Fortsetzung des Iterierens ist unnötig oder unmöglich. Dies kann durch einen fehlerhaften Wert oder eine Kündigungsanforderung verursacht werden.

  • Eine Ausnahme wird in einer Try...Catch...Finally. Sie können am Ende des Finally Blocks verwendenExit For.

  • Es gibt eine Endlosschleife, bei der es sich um eine Schleife handelt, die eine große oder sogar unendliche Anzahl von Malen ausführen kann. Wenn Sie eine solche Bedingung erkennen, können Sie Exit For verwenden, um die Schleife zu verlassen. Weitere Informationen finden Sie unter Do...Loop-Anweisung.

Iteratoren

Sie verwenden einen Iterator , um eine benutzerdefinierte Iteration über eine Sammlung durchzuführen. Ein Iterator kann eine Funktion oder ein Get Accessor sein. Sie verwendet eine Yield Anweisung, um jedes Element der Auflistung 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. Die Ausführung wird von diesem Speicherort neu gestartet, wenn der Iterator das nächste Mal aufgerufen wird.

Im folgenden Beispiel wird eine Iteratorfunktion verwendet. Die Iteratorfunktion weist eine Yield Anweisung auf, die sich in einem For befindet... 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 fortfährt.

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... Next -Anweisung wird ausgeführt, Visual Basic wertet die Auflistung nur einmal aus, bevor die Schleife gestartet wird. Wenn sich ihr Anweisungsblock ändert element oder groupsich diese Ä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 element explizit zu deklarieren. Sofern der Datentyp des Elements nicht außerhalb des For Each...Next -Konstrukts definiert ist, ist sein Bereich 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. Dies verbessert die Lesbarkeit Ihres Programms, 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 das Ändern des Werts innerhalb element einer Schleife vermeiden. Dadurch kann es schwieriger werden, Den Code zu lesen und zu debuggen. Das Ändern des Werts wirkt group sich nicht auf die Auflistung oder die zugehörigen Elemente aus, die beim ersten Eingeben der Schleife bestimmt wurden.

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

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 kennen die Merkmale des Enumeratorobjekts, das die Auflistung verfügbar macht. Die Reihenfolge der Traversal wird von Visual Basic nicht bestimmt, sondern von der MoveNext Methode des Enumeratorobjekts. Daher können Sie möglicherweise nicht vorhersagen, in welchem Element der Auflistung das erste element zurückgegeben elementwerden soll oder welches das nächste element nach einem bestimmten Element zurückgegeben werden soll. Sie können zuverlässigere Ergebnisse erzielen, indem Sie eine andere Schleifenstruktur verwenden, z For. B. ...Next oder Do...Loop.

Die Laufzeit muss in der Lage sein, die Elemente in groupelement. Die [Option Strict] -Anweisung steuert, ob sowohl Verbreiterungs- als auch Verengungskonvertierungen zulässig sind (Option Strict ist deaktiviert, Standardwert) oder ob nur Verbreiterungskonvertierungen zulässig sind (Option Strict ist aktiviert). Weitere Informationen finden Sie unter Schmalungskonvertierungen.

Der Datentyp muss group ein Bezugstyp sein, der sich auf eine Auflistung oder ein Array bezieht, das aufgezählt werden kann. Dies bedeutet am häufigsten, dass group sich auf ein Objekt bezieht, 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 Enumerationsobjekt für die Auflistung zurückgibt. Das Enumerationsobjekt implementiert die Schnittstelle des System.Collections Namespaces und macht die Current Eigenschaft und die Reset Methoden verfügbarMoveNext.System.Collections.IEnumerator Visual Basic verwendet diese zum Durchlaufen der Auflistung.

Eingrenzungskonvertierungen

Wenn Option Strict diese Einstellung auf On"Verengung" festgelegt ist, führen Konvertierungen in der Regel zu Compilerfehlern. In einer For Each Anweisung werden jedoch Konvertierungen aus den Elementen group in die element 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 nicht n kompiliert, wenn Option Strict sie aktiviert ist, da es sich bei der Konvertierung eines Long In-Elements Integer um eine schmale Konvertierung handelt. In der For Each Anweisung wird jedoch kein Compilerfehler gemeldet, obwohl die Zuordnung number dieselbe Konvertierung von Long zu erfordert Integer. 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 dies nicht der Fehler 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 angegeben wird, dass kein nächstes Element vorhanden ist, d. h., wenn die Auflistung leer ist, wird die For Each Schleife beendet und das Steuerelement an die Anweisung übergeben, die auf die Next Anweisung folgt. Andernfalls legt element Visual Basic auf das erste Element fest und führt den Anweisungsblock aus.

Jedes Mal, wenn Visual Basic auf die Next Anweisung trifft, wird sie an die For Each Anweisung zurückgegeben. Erneut wird das Element 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 gefunden wird.

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

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

Ändern von Auflistungselementen. Die Current Eigenschaft des Enumerationsobjekts ist ReadOnly und gibt eine lokale Kopie der einzelnen Auflistungselemente zurück. Dies bedeutet, dass Sie die Elemente nicht selbst in einer ...Next -For EachSchleife ä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 Sammlung 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 der einzelnen thisControl Elemente 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 ...Next -For EachSchleife 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 im Verzeichnis "C:\" mithilfe der DirectoryInfo Klasse aufgelistet.

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

Im folgenden Beispiel wird eine Prozedur zum Sortieren einer Auflistung veranschaulicht. Im Beispiel werden Instanzen einer Car Klasse sortiert, die in einer List<T>. Die Car Klasse implementiert die IComparable<T> Schnittstelle, die erfordert, dass die CompareTo Methode implementiert wird.

Jeder Aufruf der Methode führt einen einzelnen Vergleich aus, der für die CompareTo Sortierung verwendet wird. Vom Benutzer geschriebener 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 als das andere Objekt ist, größer als Null, wenn das aktuelle Objekt größer als das andere Objekt ist, und Null, wenn sie gleich sind. Auf diese Weise können Sie im Code die Kriterien für größer als, kleiner als und gleich definieren.

In der ListCars Methode sortiert die cars.Sort() Anweisung die Liste. Dieser Aufruf der Methode Sort von List<T> bewirkt, dass die Methode CompareTo automatisch für die Objekte Car in List 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