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

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

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

Bestandteile

Ausdruck

Definition

element

In der For Each-Anweisung erforderlich. In der Next-Anweisung optional. Variable. Wird zum Durchlaufen der Elemente der Auflistung verwendet.

datatype

Erforderlich, wenn element noch nicht deklariert ist. Vom Datentyp element.

group

Erforderlich. Objektvariable. Verweist auf die Auflistung, in der die statements wiederholt werden sollen.

statements

Optional. Eine oder mehrer Anweisungen zwischen For Each und Next, die für jedes Element in group ausgeführt werden.

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.

Hinweise

Verwenden Sie eine For Each...Next-Schleife, wenn für jedes Element einer Auflistung oder eines Arrays ein Satz von Anweisungen wiederholt werden soll.

Visual Basic wertet die Auflistung nur einmal, vor Beginn die Schleife, aus. Wenn der Anweisungsblock element oder group ändert, wirken sich diese Änderungen nicht auf die Iteration der Schleife aus.

Nachdem element alle Elemente in der Auflistung zugewiesen wurden, wird die For Each-Schleife beendet und die Steuerung an die Anweisung nach der Next-Anweisung übergeben.

Wenn element nicht außerhalb dieser Schleife deklariert wurde, müssen Sie es in der For Each-Anweisung deklarieren. Sie können den Typ element explizit durch eine As-Anweisung deklarieren, oder Sie können auf den Typrückschluss zur Zuweisung des Typs zurückgreifen. In beiden Fällen liegt der Gültigkeitsbereich von element innerhalb der Schleife. Sie können element jedoch nicht sowohl außerhalb als auch innerhalb der Schleife deklarieren.

Sie können element in der Next-Anweisung optional angeben. Dies verbessert die Lesbarkeit des Programms, besonders, wenn Sie For Each-Schleifen geschachtelt haben. Sie müssen dieselbe Variable angeben, die in der entsprechenden For Each-Anweisung vorhanden ist.

Vielleicht möchten Sie den Wert von element in einer Schleife nicht verändern müssen. Dadurch kann machen es schwieriger sein, Code zu lesen und zu debuggen. Das Ändern des Werts von group wirkt sich nicht auf die Auflistung oder ihre Elemente aus, die zu Beginn der Schleife bestimmt wurden.

Tipp

Eine For...Next-Anweisung (Visual Basic) eignet sich gut, wenn jede Iteration einer Schleife einer Steuerelementvariablen zugeordnet und der Anfangs- und Endwert der Variablen bestimmt werden kann. Für eine Auflistung ist das Konzept von Anfangs- und Endwert jedoch bedeutungslos, und Sie kennen nicht unbedingt die Anzahl der Elemente in der Auflistung. In diesem Fall ist eine For Each...Next-Schleife besser geeignet.

Wenn der Code die Auflistung in einer bestimmten Reihenfolge durchlaufen muss, ist eine For Each...Next-Schleife nicht die optimale Lösung, es sei denn, Sie kennen die Merkmale des Enumerationsobjekts, das von der Auflistung verfügbar gemacht wird. Die Reihenfolge des Durchlaufs wird nicht durch Visual Basic festgelegt, sondern von der MoveNext-Methode des Enumerationsobjekts. Das bedeutet, dass Sie u. U. nicht vorhersagen können, welches Element der Auflistung als erstes in element zurückgegeben wird oder welches als nächstes Element nach einem bestimmten anderen Element zurückgegeben wird. Zuverlässigere Ergebnisse erzielen Sie möglicherweise mit einer anderen Schleife, z. B. For...Next oder Do...Loop..

Schachteln von Schleifen

Sie können For Each-Schleifen schachteln, indem Sie eine Schleife in eine andere einfügen. Jede Schleife erfordert jedoch eine eindeutige element-Variable.

Sie können auch unterschiedliche Arten von Steuerungsstrukturen ineinander schachteln. Weitere Informationen finden Sie unter Geschachtelte Steuerungsstrukturen (Visual Basic).

Wenn eine Next-Anweisung einer äußeren Schachtelungsebene vor der Next-Anweisung einer inneren Ebene auftritt, signalisiert der Compiler einen Fehler. Der Compiler kann diesen Überlappungsfehler nur erkennen, wenn Sie in jeder Next-Anweisung element angeben.

Beenden für

Die Exit For-Anweisung führt zum Beenden der For…Next-Schleife und übergibt die Steuerung an die Anweisung nach der Next-Anweisung.

Sie können eine beliebige Anzahl von Exit For-Anweisungen in einer For Each-Schleife einfügen. Bei Verwendung in geschachtelten For Each-Schleifen beendet Exit For die innerste Schleife und überträgt die Steuerung auf die nächsthöhere Schachtelungsebene.

Exit For wird oft nach der Auswertung einer Bedingung verwendet, z. B. in einer If...Then...Else-Struktur. Sie können Exit For für die folgenden Bedingungen verwenden möchten:

  • Das weitere Durchlaufen ist unnötig oder unmöglich. Dies kann durch einen falschen Wert oder eine Beendigungsanforderung verursacht werden.

  • Eine Ausnahme wird abgefangen in Try...Catch...Finally. Sie können am Ende des Finally-Blocks Exit For verwenden.

  • Dort eine Endlos-Schleife, die eine Schleife ist, die eine große oder sogar unendliche Anzahl von Wiederholungen ausgeführt werden kann. Wenn Sie eine solche Bedingung feststellen, können Sie Exit For verwenden, um die Schleife zu verlassen. Weitere Informationen finden Sie unter Do...Loop-Anweisung (Visual Basic).

Die Continue For-Anweisung überträgt die Steuerung direkt an die nächste Iteration der Schleife. Weitere Informationen finden Sie unter Continue-Anweisung (Visual Basic).

Datentypen

Für element muss ein Datentyp verwendet werden, in den der Datentyp der Elemente von group konvertiert werden kann.

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

Die Elemente von group sind normalerweise vom Typ Object, können jedoch einen beliebigen Laufzeitdatentyp aufweisen.

Eingrenzende Konvertierungen

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

im folgenden Beispiel kompiliert die Zuweisung von m als Anfangswert für n nicht mit Option Strict, da die Konvertierung von Long zu Integer eine einschränkende Konvertierung ist. In der For Each-Anweisung wird jedoch kein Compilerfehler gemeldet, obwohl die Zuordnung zu number dieselbe Konvertierung von Long in Integer erfordert. In der For Each-Anweisung, die eine große Anzahl enthält, tritt ein Laufzeitfehler auf, wenn ToInteger auf die große Anzahl angewendet wird.

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, 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

        Console.ReadKey()
    End Sub
End Module

IEnumerator-Aufrufe

Zu Beginn der Ausführung einer For Each...Next-Schleife überprüft Visual Basic, ob die group auf ein gültiges Auflistungsobjekt verweist. Wenn dies nicht der Fall ist, wird eine Ausnahme ausgelöst. Andernfalls werden die MoveNext-Methode und die Current-Eigenschaft des Operatorobjekts aufgerufen, um das erste Element zurückzugeben. Wenn MoveNext angibt, dass kein nächstes Elemente vorhanden ist, die Auflistung also leer ist, wird die For Each-Schleife beendet, und die Steuerung wird an die Anweisung nach der Next-Anweisung übergeben. Andernfalls legt Visual Basic element auf das erste Element fest und führt den Anweisungsblock aus.

Visual Basic setzt bei jedem Auftreten der Next-Anweisung die Ausführung mit der For Each-Anweisung fort. Erneut werden MoveNext und Current aufgerufen, um das nächste Element zurückzugeben, und erneut wird je nach Ergebnis entweder der Block ausgeführt oder die Schleife beendet. Dieser Prozess wird fortgesetzt, bis MoveNext angibt, dass kein nächstes Element vorhanden ist oder bis eine Exit For-Anweisung auftritt.

Änderungen

Ändern der Auflistung. Das von GetEnumerator zurückgegebene Enumerationsobjekt gestattet es normalerweise nicht, die Auflistung durch Hinzufügen, Löschen, Ersetzen oder Neuordnen von Elementen zu ändern. Wenn Sie die Auflistung ändern, nachdem Sie eine For Each...Next-Schleife gestartet haben, wird das Enumerationsobjekt ungültig, und der nächste Versuch des Zugriffs auf ein Element führt zu einer InvalidOperationException-Ausnahme.

Diese Blockierung der Änderung ist jedoch nicht von Visual Basic bedingt, sondern liegt an der Implementierung der IEnumerable-Schnittstelle. IEnumerable kann auf eine Weise implementiert werden, die Änderungen während der Iteration zulässt. Für die Durchführung einer solchen dynamischen Änderung sollten Sie mit den Merkmalen der IEnumerable-Implementierung für die verwendete Auflistung vertraut sein.

Ändern von Auflistungselementen. Die Current-Eigenschaft des Enumerationsobjekts ist ReadOnly (Visual Basic) und gibt eine lokale Kopie jedes Auflistungselements zurück. Das bedeutet, dass Sie die eigentlichen Elemente in einer For Each...Next-Schleife nicht ändern können. Jede Änderung, die Sie durchführen, betrifft nur die lokale Kopie von Current und wird in der zugrunde liegenden Auflistung nicht übernommen. Wenn ein Element jedoch ein Verweistyp ist, können Sie die Member der Instanz ändern, auf die es zeigt. Dies wird anhand des folgenden Beispiels veranschaulicht:

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

Im vorherigen Beispiel kann der BackColor-Member jedes thisControl-Elements geändert werden, obwohl thisControl selbst nicht geändert werden kann.

Traversieren von Arrays. Da die Array-Klasse die IEnumerable-Schnittstelle implementiert, machen alle Arrays die GetEnumerator-Methode verfügbar. Das bedeutet, dass Sie ein Array mit einer For Each...Next-Schleife traversieren können. Jedoch können Sie nur die Array-Elemente lesen. Sie können nicht geändert werden. Informationen zur Veranschaulichung finden Sie unter Gewusst wie: Ausführen mehrerer Anweisungen für jedes einzelne Element in einer Auflistung oder einem Array (Visual Basic).

Beispiel

Im folgenden Beispiel wird die Verwendung der For Each…Next-Anweisung veranschaulicht.

' 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

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 

Das folgende Beispiel veranschaulicht, wie die Continue For-Anweisung und die Exit For-Anweisung 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 7, 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

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

Im folgenden Beispiel wird veranschaulicht, wie eine Auflistung mit der IComparable-Schnittstelle sortiert 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
        ' Determine the relative order of the objects being compared.
        ' This is used to 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

Das folgende Beispiel enthält eine benutzerdefinierte Auflistungsklasse, die einen benutzerdefinierten Enumerator verwendet.

Public Sub ListColors()
    Dim colors As New AllColors()

    For Each theColor As Color In colors
        Debug.Write(theColor.Name & " ")
    Next
    Debug.WriteLine("")
    ' Output: red blue green
End Sub

' Collection class.
Public Class AllColors
    Implements System.Collections.IEnumerable

    Private _colors() As Color =
    {
        New Color With {.Name = "red"},
        New Color With {.Name = "blue"},
        New Color With {.Name = "green"}
    }

    Public Function GetEnumerator() As System.Collections.IEnumerator _
        Implements System.Collections.IEnumerable.GetEnumerator

        Return New ColorEnumerator(_colors)

        ' Instead of creating a using a custom enumerator, you could
        ' use the GetEnumerator of the array.
        'Return _colors.GetEnumerator
    End Function

    ' Custom enumerator.
    Private Class ColorEnumerator
        Implements System.Collections.IEnumerator

        Private _colors() As Color
        Private _position As Integer = -1

        Public Sub New(ByVal colors() As Color)
            _colors = colors
        End Sub

        Public ReadOnly Property Current() As Object Implements System.Collections.IEnumerator.Current
            Get
                Return _colors(_position)
            End Get
        End Property

        Public Function MoveNext() As Boolean Implements System.Collections.IEnumerator.MoveNext
            _position += 1
            Return (_position < _colors.Length)
        End Function

        Public Sub Reset() Implements System.Collections.IEnumerator.Reset
            _position = -1
        End Sub
    End Class
End Class

' Element class.
Public Class Color
    Public Property Name As String
End Class

Siehe auch

Aufgaben

Gewusst wie: Ausführen mehrerer Anweisungen für jedes einzelne Element in einer Auflistung oder einem Array (Visual Basic)

Referenz

For...Next-Anweisung (Visual Basic)

While...End While-Anweisung (Visual Basic)

Do...Loop-Anweisung (Visual Basic)

Konzepte

Schleifenstruktur (Visual Basic)

Auflistungen in Visual Basic

Erweiternde und eingrenzende Konvertierungen (Visual Basic)

Objektinitialisierer: Benannte und anonyme Typen (Visual Basic)

Übersicht über Auflistungsinitialisierer (Visual Basic)

Arrays in Visual Basic

Änderungsprotokoll

Datum

Versionsgeschichte

Grund

Dezember 2010

Abschnitt mit Hinweisen neu organisiert und Beispiele hinzugefügt.

Informationsergänzung.