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 ]
Teile
Begriff |
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 nicht bereits deklariert wird.Vom Datentyp element. |
group |
Erforderlich.Eine Variable mit einem Typ, der ein Auflistung Typ oder ein - Objekt ist.Verweist auf die Auflistung, in der die statements wiederholt werden sollen. |
statements |
Dies ist optional.Eine oder mehrer Anweisungen zwischen For Each und Next, die für jedes Element in group ausgeführt werden. |
Continue For |
Dies ist optional.Überträgt die Steuerung an den Anfang der For Each-Schleife. |
Exit For |
Dies ist optional.Überträgt die Steuerung aus der For Each-Schleife. |
Next |
Erforderlich.Beendet die Definition der For Each-Schleife. |
Einfaches Beispiel
Verwenden Sie eine For Each...Next-Schleife, wenn für jedes Element einer Auflistung oder eines Arrays ein Satz von Anweisungen wiederholt werden soll.
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.Wenn Sie jedoch eine Auflistung arbeiten, ist das Konzept der ersten und der endgültigen Werte nicht sinnvoll, und Sie nicht unbedingt wissen, wie viele Elemente die Auflistung verfügt.In dieser Art des Falls, ist eine - Schleife For Each...Next häufig die bessere Wahl. |
Im folgenden Beispiel wird die - Anweisung For Each...Next durch alle Elemente einer Listenauflistung durch.
' 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 Auflistungen (C# und Visual Basic) und unter Arrays in Visual Basic.
Geschachtelte - Schleifen
Sie können For Each-Schleifen schachteln, indem Sie eine Schleife in eine andere 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 schachteln, muss jede - Schleife eine eindeutige element-Variablen vorhanden sind.
Sie können auch unterschiedliche Arten von Steuerungsstrukturen ineinander schachteln.Weitere Informationen finden Sie unter Geschachtelte Steuerungsstrukturen (Visual Basic).
Beenden für und Fortfahren für fort
Die Beenden für-Anweisungsursachenausführung, um die Schleife For...Next und des Übergangssteuerelements zur Anweisung zu beenden, die der Next-Anweisung folgt.
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).
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
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).
Iteratoren
Sie verwenden einen Iterator, um eine benutzerdefinierte Iteration über einer Auflistung auszuführen.Ein Iterator kann eine Funktion oder ein Get Accessor sein.Er verwendet Yield eine - Anweisung, um jedes Element der Auflistung separat zurückzugeben.
Sie rufen den Iterator auf, indem Sie eine For Each...Next-Anweisung verwenden.Jede Iteration der Schleife For Each ruft den Iterator auf.Wenn eine Yield-Anweisung im Iterator erreicht ist, wird der Ausdruck in der Yield-Anweisung zurückgegeben, und die aktuelle Position im Code wird beibehalten.Die Ausführung von diesem Speicherort beim nächsten Mal neu gestartet, dass der Iterator aufgerufen wird.
Im folgenden Beispiel wird eine Iteratorfunktion.Die Iteratorfunktion verfügt über eine Yield-Anweisung, die innerhalb einer Für... Next-Schleife Schleife ist.In der ListEvenNumbers-Methode erstellt jede Iteration des For Each-Anweisungstexts einen Aufruf der Iteratorfunktion, die der folgenden 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 (C# und Visual Basic), Yield-Anweisung (Visual Basic) und Iterator (Visual Basic).
Technische Implementierung
Wenn eine - Anweisung For Each...Next ausgeführt wird, wertet Visual Basic die Auflistung nur einmal, bevor die Schleifenanfänge aus.Wenn das Anweisungsblock element oder group ändert, beeinflussen diese Änderungen nicht die Iteration der Schleife.
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 der Schleife deklariert wurde, müssen Sie sie 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 die Elemente, die bestimmt wurden, als die Schleife zuerst eingeführt wurde.
Wenn geschachtelte Schleifen sind, wenn eine Next-Anweisung einer äußeren Schachtelungsebene erreicht wird, bevor Next einer inneren Ebene, der Compiler einen Fehler signalisiert.Der Compiler kann diesen Überlappungsfehler nur erkennen, wenn Sie in jeder Next-Anweisung element angeben.
Wenn der Code auf dem Durchlaufen einer Auflistung in einer bestimmten Reihenfolge abhängig ist, ist eine - Schleife For Each...Next nicht die beste Wahl, es sei denn, Sie wissen, dass die Eigenschaften des Enumeratorobjekts, das die Auflistung verfügbar macht.Die Reihenfolge des Durchlaufs wird nicht von Visual Basic, aber durch die - Methode des MoveNext Enumeratorobjekts bestimmt.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..
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 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.
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 den Anfangswert für n nicht, wenn Option Strict aktiviert ist, da die Konvertierung von Long zu Integer einschränkende Konvertierung.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.
Ändern der Auflistung. Das Enumeratorobjekt, das von GetEnumerator normalerweise zurückgegeben wird, können Sie nicht die Auflistung ändern, indem es hinzugefügt wird, löscht, ersetzt, oder neu angeordnet werden alle Elemente.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.
ist jedoch Blockieren der Änderung nicht von Visual Basic, sondern durch die Implementierung der - Schnittstelle IEnumerable bestimmt.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 erstellen Sie wirkt sich nur auf die lokale Kopie von Current und nicht zurück in die zugrunde liegende Auflistung wiedergegeben.Wenn ein Element jedoch ein Verweistyp ist, können Sie die Member der Instanz ändern, auf die es zeigt.Im folgenden Beispiel ändert den BackColor-Member jedes thisControl-Elements.Sie können thisControl selbst jedoch nicht ändern.
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.
Beispiel
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
Das folgende Beispiel veranschaulicht ein Verfahren zum Sortieren einer Auflistung.Die Beispielssortierungsinstanzen von Car-Klasse, die in List<T> gespeichert werden.Die Car-Klasse implementiert die - Schnittstelle IComparable<T>, die erfordert, dass die CompareTo-Methode implementiert ist.
Jeder Aufruf der - Methode CompareTo vergleicht einzelnen, 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 als das andere - Objekt ist, größer als null, wenn das aktuelle Objekt größer als das andere - Objekt ist, und wenn sie gleich sind.Dies ermöglicht es Ihnen, in dem Code definieren die Kriterien für größer als, weniger als und gleich.
In der ListCars-Methode die cars.Sort()-Anweisungssortierungen die Liste.Dieser Aufruf der - Methode SortList<T> wird die CompareTo-Methode, für die Car-Objekte in List automatisch aufgerufen werden.
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
Referenz
For...Next-Anweisung (Visual Basic)
While...End While-Anweisung (Visual Basic)
Do...Loop-Anweisung (Visual Basic)
Konzepte
Schleifenstruktur (Visual Basic)
Erweiternde und eingrenzende Konvertierungen (Visual Basic)
Objektinitialisierer: Benannte und anonyme Typen (Visual Basic)
Auflistungsinitialisierer (Visual Basic)