For Each...Next-Anweisung (Visual Basic)
Aktualisiert: Juli 2008
Wiederholt eine Reihe von Anweisungen für jedes Element in einer Auflistung.
For Each element [ As datatype ] In group
[ statements ]
[ Exit For ]
[ statements ]
Next [ element ]
Bestandteile
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.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.
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.
Regeln
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. Dies bedeutet, dass group auf ein Objekt verweisen muss, das die IEnumerable-Schnittstelle des System.Collections-Namespaces oder die IEnumerable<T>-Schnittstelle des System.Collections.Generic-Namespaces implementiert. IEnumerable definiert die GetEnumerator-Methode, die ein Enumerationsobjekt für die Auflistung zurückgibt. Das Enumerationsobjekt implementiert die 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. 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.
Dim m As Long = 987 ' Does not compile. 'Dim n As Integer = m
Konvertierungen der Elemente in group zu element werden jedoch zur Laufzeit ausgewertet und ausgeführt, und der Fehler für einschränkende Konvertierung wird unterdrückt. Im folgenden Beispiel wird kein Compilerfehler in der Schleife For Each ausgegeben, obwohl sie dieselbe Konvertierung von Long zu Integer erfordert, die einen Fehler im vorherigen Beispiel erzeugt hat.
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. The output is 45 3 987. For Each p As Integer In New Long() {45, 3, 987} Console.Write(p & " ") Next Console.WriteLine() End Sub End Module
Das Ausbleiben eines Compilerfehlers schließt jedoch das Risiko eines Laufzeitfehlers nicht aus. Im folgenden Beispiel wird kein Compilerfehler, jedoch ein Laufzeitfehler erzeugt, wenn ToInteger auf 9876543210 angewendet wird. Der Laufzeitfehler tritt auf, gleichgültig ob Option Strict angegeben wurde.
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 = 9876543210 'Dim n As Integer = m Try ' The For Each loop requires the same conversion, but ' is not flagged by the compiler. A run-time error is ' raised because 9876543210 is too large for type Integer. For Each p As Integer In New Long() {45, 3, 9876543210} Console.Write(p & " ") Next Console.WriteLine() Catch e As System.OverflowException Console.WriteLine() Console.WriteLine(e.Message) End Try End Sub End Module
Deklaration. 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.
Anzahl von Iterationen. Visual Basic wertet die Auflistung nur einmal aus, und zwar vor Beginn der Schleife. Wenn der Anweisungsblock element oder group ändert, wirken sich diese Änderungen nicht auf die Iteration der Schleife aus.
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 in anderen Steuerungsstrukturen schachteln. Weitere Informationen finden Sie unter Geschachtelte Steuerungsstrukturen.
Hinweis: 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.
Bezeichnen der Steuerelementvariablen. 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.
Übertragen der Steuerung aus der Schleife. Die Exit-Anweisung (Visual Basic) überträgt die Steuerung direkt an die erste Anweisung nach der Next-Anweisung. Möglicherweise möchten Sie eine Schleife beenden, wenn Sie eine Bedingung feststellen, die das Fortsetzen des Durchlaufs unnötig oder unmöglich macht, z. B. ein fehlerhafter Wert oder eine Anforderung zum Beenden. Wenn Sie eine Ausnahme in einer Try...Catch...Finally-Anweisung abfangen, können Sie am Ende des Finally-Blocks Exit For verwenden.
Sie können eine beliebige Anzahl von Exit For-Anweisungen an jeder Stelle der For Each-Schleife einfügen. Exit For wird häufig nach der Auswertung einer Bedingung verwendet, z. B. in einer If...Then...Else-Struktur.
Endlosschleifen. Mit Exit For kann eine Bedingung getestet werden, die eine Endlosschleife verursachen kann. Hierbei handelt es sich um eine Schleife, die mit einer extrem großen oder unendlichen 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).
Verhalten
Einstieg in die Schleife. Zu Beginn der Ausführung der 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 an die Anweisung nach der Next-Anweisung übergeben. Andernfalls legt Visual Basic element auf das erste Element fest und führt den Anweisungsblock aus.
Iterationen der Schleife. 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.
Beenden 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.
Ändern von Iterationswerten. Wenn Sie den Wert von element während eines Schleifendurchlaufs ändern, wird unter Umständen das Lesen und Debuggen des Codes erschwert. Das Ändern des Werts von group wirkt sich nicht auf die Auflistung oder ihre Elemente aus, die zu Beginn der Schleife bestimmt wurden.
Traversalreihenfolge. Beim Ausführen einer For Each...Next-Schleife wird das Traversieren der Auflistung vom Enumerationsobjekt gesteuert, das von der GetEnumerator-Methode zurückgegeben wird. Die Traversalreihenfolge 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.
Wenn der Code vom Traversieren einer Auflistung in einer bestimmten Reihenfolge abhängt, 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. Zuverlässigere Ergebnisse erzielen Sie möglicherweise mit einer anderen Schleife, z. B. For...Next oder Do...Loop.
Ändern der Auflistung. Das von GetEnumerator zurückgegebene Enumerationsobjekt ermöglicht es Ihnen 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, dass während der Iteration Änderungen möglich sind. 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. Allerdings können Sie die Arrayelemente nur lesen, nicht ändern. Informationen zur Veranschaulichung finden Sie unter Gewusst wie: Ausführen mehrerer Anweisungen für jedes einzelne Element in einer Auflistung oder einem Array.
Beispiel
Im folgenden Beispiel wird die For Each...Next-Anweisung verwendet, um alle Elemente in einer Auflistung nach der Zeichenfolge "Hello" zu durchsuchen. Im Beispiel wird davon ausgegangen, dass die Auflistung thisCollection bereits erstellt wurde und dass ihre Elemente vom Typ String sind.
Dim found As Boolean = False
Dim thisCollection As New Collection
For Each thisObject As String In thisCollection
If thisObject = "Hello" Then
found = True
Exit For
End If
Next thisObject
Siehe auch
Aufgaben
Gewusst wie: Verbessern der Leistung einer Schleife
Konzepte
Erweiternde und eingrenzende Konvertierungen
Referenz
While...End While-Anweisung (Visual Basic)
Do...Loop-Anweisung (Visual Basic)
Änderungsprotokoll
Date |
Versionsgeschichte |
Grund |
---|---|---|
Juli 2008 |
Abschnitt über einschränkende Konvertierungen hinzugefügt. |
Kundenfeedback. |