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
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)
Übersicht über Auflistungsinitialisierer (Visual Basic)
Änderungsprotokoll
Datum |
Versionsgeschichte |
Grund |
Dezember 2010 |
Abschnitt mit Hinweisen neu organisiert und Beispiele hinzugefügt. |
Informationsergänzung. |