For Each...Next Statements
The For Each...Next loop is similar to the For...Next loop, but it executes the statement block for each element in a collection, instead of a specified number of times. The syntax is as follows:
For Each elementvariable [ As datatype ] In collection ' Statement block to be executed for each value of elementvariable. Next [ elementvariable ]
The elements of collection can be of any data type. The data type of elementvariable must be such that each element of the collection can be converted to it.
If elementvariable is not declared outside the loop, you can use the As clause to declare it as part of the For Each statement.
For each iteration of the loop, Visual Basic sets the variable elementvariable to one of the elements in the collection and executes the statement block. When all the elements in the collection have been assigned to elementvariable, the For Each loop terminates and control passes to the statement following the Next statement.
You can optionally specify the element variable in the Next statement. This improves the readability of your program. You must specify the same variable as the one that appears in the For Each statement.
The following procedure accepts a form and sets the background color of every control in that form to light blue:
Sub LightBlueBackground(ByVal ThisForm As System.Windows.Forms.Form) Dim ThisControl As System.Windows.Forms.Control For Each ThisControl In ThisForm.Controls ThisControl.BackColor = System.Drawing.Color.LightBlue Next ThisControl End Sub
The collection must be an object that implements the IEnumerable interface of the System.Collections namespace. IEnumerable defines the GetEnumerator method, which returns an enumerator object for the collection. The enumerator object exposes the Current property and the MoveNext method. Visual Basic uses these to traverse the collection. The data type of the elements returned by Current must be convertible to the data type of elementvariable.
The Current property of the enumerator object is ReadOnly, and it returns a local copy of each collection element. This means that you cannot modify the elements themselves in a For Each...Next loop. Any modification you make affects only the local copy from Current and is not reflected back into the collection. However, if an element is a reference type, you can modify the members of the instance to which it points. This is why, in the previous example, you can modify the
BackColor member of each
ThisControl element, although you cannot modify
Because System.Array implements the IEnumerable interface, all arrays expose the GetEnumerator method. This means you can iterate through an array with a For Each...Next loop. However, you can only read the array elements, not change them. The following procedure is intended to find the sum of the elements of an array and reset each element to zero:
Function SumAndReset(ByRef A() As Integer) As Integer Dim Elt As Integer Dim Sum As Integer = 0 For Each Elt In A Sum += Elt Elt = 0 Next Elt Return Sum End Function
The summation works as intended because it relies only on reading the elements. However, the resetting to zero does not work as intended, because only the local copy is reset to zero, while the original element is left unchanged in the collection.
Altering the Collection
The enumerator object does not allow you to alter the collection by adding, deleting, replacing, or reordering any elements. If you alter the collection after you have initiated a For Each...Next loop, the enumerator object becomes invalid, and the next attempt to access an element results in an InvalidOperationException.
Traversing the Collection
When you execute a For Each...Next loop, traversal of the collection is under the control of the enumerator object returned by the GetEnumerator method. The order of traversal is not determined by Visual Basic, but rather by the MoveNext method of the enumerator object. This means that you might not be able to predict which element of the collection is the first to be returned in elementvariable, or which is the next to be returned after a given element.
If your code depends on traversing a collection in a particular order, a For Each...Next loop is not the best choice unless you know the characteristics of the enumerator object the collection exposes. You might achieve more reliable results using a different loop, such as For...Next or Do...Loop.
Exiting a For Each...Next Loop Before It Is Finished with the Collection
You can exit a For Each...Next loop before it has traversed the collection by using the Exit For statement. For example, you might want to exit a loop if you detect a condition that makes it unnecessary or impossible to continue iterating, such as an erroneous value or a termination request. Also, if you catch an exception in a Try...Catch...Finally, you can use Exit For at the end of the Finally block.
Decision Structures | Nested Control Statements | For Each...Next Statements (Language Reference) | Do...Loop Statements | While Statement | For...Next Statements | Exit Statement | Try...Catch...Finally Statements | Form Class | Control Class | Color Structure | IEnumerable Interface | IEnumerable.GetEnumerator Method | IEnumerator.Current Property | Array Class | Array.GetEnumerator Method