Instrucción For Each...Next (Visual Basic)For Each...Next Statement (Visual Basic)

Repite un grupo de instrucciones para cada elemento de una colección.Repeats a group of statements for each element in a collection.

SintaxisSyntax

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

ElementosParts

TérminoTerm DefiniciónDefinition
element Obligatorio en la instrucción For Each.Required in the For Each statement. Opcional en la instrucción Next.Optional in the Next statement. Variable.Variable. Se utiliza para recorrer en iteración los elementos de la colección.Used to iterate through the elements of the collection.
datatype Opcional si Option Infer es on (el valor predeterminado) o element ya está declarado; obligatorio si Option Infer está desactivado y element no se ha declarado ya.Optional if Option Infer is on (the default) or element is already declared; required if Option Infer is off and element isn't already declared. Tipo de datos de element.The data type of element.
group Obligatorio.Required. Una variable con un tipo que es un tipo de colección o un objeto.A variable with a type that's a collection type or Object. Hace referencia a la colección en la que se va a repetir el statements.Refers to the collection over which the statements are to be repeated.
statements Opcional.Optional. Una o varias instrucciones entre For Each y Next que se ejecutan en cada elemento de group.One or more statements between For Each and Next that run on each item in group.
Continue For Opcional.Optional. Transfiere el control al principio del bucle @no__t 0.Transfers control to the start of the For Each loop.
Exit For Opcional.Optional. Transfiere el control fuera del bucle @no__t 0.Transfers control out of the For Each loop.
Next Obligatorio.Required. Finaliza la definición del bucle For Each.Terminates the definition of the For Each loop.

Ejemplo sencilloSimple Example

Use un bucle For Each... Next cuando desee repetir un conjunto de instrucciones para cada elemento de una colección o matriz.Use a For Each...Next loop when you want to repeat a set of statements for each element of a collection or array.

Sugerencia

Una para... La siguiente instrucción funciona bien cuando se puede asociar cada iteración de un bucle a una variable de control y determinar los valores iniciales y finales de la variable.A For...Next Statement works well when you can associate each iteration of a loop with a control variable and determine that variable's initial and final values. Sin embargo, cuando se trabaja con una colección, el concepto de valores iniciales y finales no es significativo y no se sabe necesariamente cuántos elementos tiene la colección.However, when you are dealing with a collection, the concept of initial and final values isn't meaningful, and you don't necessarily know how many elements the collection has. En este tipo de caso, un bucle For Each... Next suele ser una mejor opción.In this kind of case, a For Each...Next loop is often a better choice.

En el ejemplo siguiente, el For Each... NextIn the following example, the For EachNext la instrucción recorre en iteración todos los elementos de una colección de lista.statement iterates through all the elements of a List collection.

' 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

Para obtener más ejemplos, vea colecciones y matrices.For more examples, see Collections and Arrays.

Bucles anidadosNested Loops

Puede anidar bucles For Each colocando un bucle dentro de otro.You can nest For Each loops by putting one loop within another.

En el ejemplo siguiente se muestra @no__t anidadas-0... NextThe following example demonstrates nested For EachNext obra.structures.

' 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 

Al anidar bucles, cada bucle debe tener una variable element única.When you nest loops, each loop must have a unique element variable.

También puede anidar distintos tipos de estructuras de control entre sí.You can also nest different kinds of control structures within each other. Para obtener más información, vea estructuras de control anidadas.For more information, see Nested Control Structures.

Salir de y continuar paraExit For and Continue For

La instrucción Exit for hace que la ejecución salga del For... NextThe Exit For statement causes execution to exit the ForNext bucle y transfiere el control a la instrucción que sigue a la instrucción Next.loop and transfers control to the statement that follows the Next statement.

La instrucción Continue For transfiere el control inmediatamente a la siguiente iteración del bucle.The Continue For statement transfers control immediately to the next iteration of the loop. Para obtener más información, vea instrucción continue.For more information, see Continue Statement.

En el ejemplo siguiente se muestra cómo usar las instrucciones Continue For y Exit For.The following example shows how to use the Continue For and Exit For statements.

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

Puede incluir cualquier número de instrucciones Exit For en un bucle For Each.You can put any number of Exit For statements in a For Each loop. Cuando se usa en bucles For Each anidados, Exit For hace que la ejecución salga del bucle más interno y transfiere el control al siguiente nivel superior de anidamiento.When used within nested For Each loops, Exit For causes execution to exit the innermost loop and transfers control to the next higher level of nesting.

Exit For suele usarse después de una evaluación de alguna condición, por ejemplo, en una estructura If... Then... Else.Exit For is often used after an evaluation of some condition, for example, in an If...Then...Else structure. Es posible que desee usar Exit For para las siguientes condiciones:You might want to use Exit For for the following conditions:

  • Continuar la iteración no es necesario o imposible.Continuing to iterate is unnecessary or impossible. Esto puede deberse a un valor erróneo o a una solicitud de finalización.This might be caused by an erroneous value or a termination request.

  • Se detectó una excepción en un Try... Catch... Finally. Puede usar Exit For al final del bloque Finally.An exception is caught in a Try...Catch...Finally. You might use Exit For at the end of the Finally block.

  • Hay un bucle interminable, que es un bucle que podría ejecutar un número de veces grande o incluso infinito.There an endless loop, which is a loop that could run a large or even infinite number of times. Si detecta este tipo de condición, puede usar Exit For para escapar el bucle.If you detect such a condition, you can use Exit For to escape the loop. Para obtener más información, vea.. . Instrucción Loop.For more information, see Do...Loop Statement.

IteratorsIterators

Un iterador se usa para realizar una iteración personalizada en una colección.You use an iterator to perform a custom iteration over a collection. Un iterador puede ser una función o un descriptor de acceso Get.An iterator can be a function or a Get accessor. Usa una instrucción Yield para devolver cada elemento de la colección de uno en uno.It uses a Yield statement to return each element of the collection one at a time.

Se llama a un iterador mediante una instrucción For Each...Next.You call an iterator by using a For Each...Next statement. Cada iteración del bucle For Each llama al iterador.Each iteration of the For Each loop calls the iterator. Cuando se alcanza una instrucción Yield en el iterador, se devuelve la expresión de la instrucción Yield y se conserva la ubicación actual en el código.When a Yield statement is reached in the iterator, the expression in the Yield statement is returned, and the current location in code is retained. La ejecución se reinicia desde esa ubicación la próxima vez que se llama al iterador.Execution is restarted from that location the next time that the iterator is called.

En el ejemplo siguiente se utiliza una función de iterador.The following example uses an iterator function. La función de iterador tiene una instrucción Yield que se encuentra dentro de un ... Siguiente bucle.The iterator function has a Yield statement that's inside a For…Next loop. En el método ListEvenNumbers, cada iteración del cuerpo de la instrucción For Each crea una llamada a la función de iterador, que continúa con la siguiente instrucción Yield.In the ListEvenNumbers method, each iteration of the For Each statement body creates a call to the iterator function, which proceeds to the next Yield statement.

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

Para obtener más información, vea iteradores, instrucción yielde iterator.For more information, see Iterators, Yield Statement, and Iterator.

Implementación técnicaTechnical Implementation

Cuando For Each... NextWhen a For EachNext la instrucción se ejecuta, Visual Basic evalúa la colección solo una vez, antes de que se inicie el bucle.statement runs, Visual Basic evaluates the collection only one time, before the loop starts. Si el bloque de instrucciones cambia element o group, estos cambios no afectan a la iteración del bucle.If your statement block changes element or group, these changes don't affect the iteration of the loop.

Cuando todos los elementos de la colección se han asignado sucesivamente a element, el bucle For Each se detiene y el control pasa a la instrucción que sigue a la instrucción Next.When all the elements in the collection have been successively assigned to element, the For Each loop stops and control passes to the statement following the Next statement.

Si Option Infer es on (su configuración predeterminada), el compilador Visual Basic puede deducir el tipo de datos de element.If Option Infer is on (its default setting), the Visual Basic compiler can infer the data type of element. Si está desactivado y element no se ha declarado fuera del bucle, debe declararlo en la instrucción For Each.If it is off and element hasn't been declared outside the loop, you must declare it in the For Each statement. Para declarar el tipo de datos de element explícitamente, use una cláusula As.To declare the data type of element explicitly, use an As clause. A menos que el tipo de datos del elemento esté definido fuera de la construcción For Each... Next, su ámbito es el cuerpo del bucle.Unless the data type of element is defined outside the For Each...Next construct, its scope is the body of the loop. Tenga en cuenta que no puede declarar element fuera y dentro del bucle.Note that you cannot declare element both outside and inside the loop.

Opcionalmente, puede especificar element en la instrucción Next.You can optionally specify element in the Next statement. Esto mejora la legibilidad del programa, sobre todo si tiene bucles For Each anidados.This improves the readability of your program, especially if you have nested For Each loops. Debe especificar la misma variable que la que aparece en la instrucción For Each correspondiente.You must specify the same variable as the one that appears in the corresponding For Each statement.

Puede que desee evitar cambiar el valor de element dentro de un bucle.You might want to avoid changing the value of element inside a loop. Esto puede dificultar la lectura y depuración del código.Doing this can make it more difficult to read and debug your code. Cambiar el valor de group no afecta a la colección ni a sus elementos, que se determinaron cuando se escribió el bucle por primera vez.Changing the value of group doesn't affect the collection or its elements, which were determined when the loop was first entered.

Al anidar bucles, si se encuentra una instrucción Next de un nivel de anidamiento externo antes del Next de un nivel interno, el compilador señala un error.When you're nesting loops, if a Next statement of an outer nesting level is encountered before the Next of an inner level, the compiler signals an error. Sin embargo, el compilador puede detectar este error superpuesto solo si se especifica element en cada instrucción Next.However, the compiler can detect this overlapping error only if you specify element in every Next statement.

Si el código depende de atravesar una colección en un orden determinado, un bucle For Each... Next no es la mejor opción, a menos que conozca las características del objeto de enumerador que expone la colección.If your code depends on traversing a collection in a particular order, a For Each...Next loop isn't the best choice, unless you know the characteristics of the enumerator object the collection exposes. Visual Basic, pero con el método MoveNext del objeto de enumerador, no determina el orden de recorrido.The order of traversal isn't determined by Visual Basic, but by the MoveNext method of the enumerator object. Por lo tanto, es posible que no pueda predecir qué elemento de la colección es el primero que se devolverá en element, o que es el siguiente que se devolverá después de un elemento determinado.Therefore, you might not be able to predict which element of the collection is the first to be returned in element, or which is the next to be returned after a given element. Podría obtener resultados más confiables mediante una estructura de bucle diferente, como For... Next o Do... Loop.You might achieve more reliable results using a different loop structure, such as For...Next or Do...Loop.

El tiempo de ejecución debe ser capaz de convertir los elementos de group a element.The runtime must be able to convert the elements in group to element. La instrucción [Option Strict] controla si se permiten las conversiones de ampliación y de restricción (Option Strict está desactivada, su valor predeterminado) o si solo se permiten conversiones de ampliación (@no__t 2 está activada).The [Option Strict] statement controls whether both widening and narrowing conversions are allowed (Option Strict is off, its default value), or whether only widening conversions are allowed (Option Strict is on). Para obtener más información, vea conversiones de restricción.For more information, see Narrowing conversions.

El tipo de datos de group debe ser un tipo de referencia que haga referencia a una colección o una matriz que sea Enumerable.The data type of group must be a reference type that refers to a collection or an array that's enumerable. Normalmente, esto significa que group hace referencia a un objeto que implementa la interfaz IEnumerable del espacio de nombres System.Collections o la interfaz IEnumerable<T> del espacio de nombres System.Collections.Generic.Most commonly this means that group refers to an object that implements the IEnumerable interface of the System.Collections namespace or the IEnumerable<T> interface of the System.Collections.Generic namespace. System.Collections.IEnumerable define el método GetEnumerator, que devuelve un objeto de enumerador para la colección.System.Collections.IEnumerable defines the GetEnumerator method, which returns an enumerator object for the collection. El objeto de enumerador implementa la interfaz System.Collections.IEnumerator del espacio de nombres System.Collections y expone la propiedad Current y los métodos Reset y MoveNext.The enumerator object implements the System.Collections.IEnumerator interface of the System.Collections namespace and exposes the Current property and the Reset and MoveNext methods. Visual Basic los usa para recorrer la colección.Visual Basic uses these to traverse the collection.

conversiones de restricciónNarrowing Conversions

Cuando Option Strict se establece en On, las conversiones de restricción suelen producir errores del compilador.When Option Strict is set to On, narrowing conversions ordinarily cause compiler errors. Sin embargo, en una instrucción For Each, las conversiones de los elementos de group a element se evalúan y se realizan en tiempo de ejecución, y se suprimen los errores del compilador causados por las conversiones de restricción.In a For Each statement, however, conversions from the elements in group to element are evaluated and performed at run time, and compiler errors caused by narrowing conversions are suppressed.

En el ejemplo siguiente, la asignación de m como el valor inicial de n no se compila cuando @no__t 2 es on porque la conversión de un Long a un Integer es una conversión de restricción.In the following example, the assignment of m as the initial value for n doesn't compile when Option Strict is on because the conversion of a Long to an Integer is a narrowing conversion. Sin embargo, en la instrucción For Each, no se genera ningún error del compilador, aunque la asignación a number requiere la misma conversión de Long a Integer.In the For Each statement, however, no compiler error is reported, even though the assignment to number requires the same conversion from Long to Integer. En la instrucción For Each que contiene un número grande, se produce un error en tiempo de ejecución cuando se aplica ToInteger al número grande.In the For Each statement that contains a large number, a run-time error occurs when ToInteger is applied to the large number.

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

Llamadas IEnumeratorIEnumerator Calls

Cuando se inicia la ejecución de un bucle For Each... Next, Visual Basic comprueba que group hace referencia a un objeto de colección válido.When execution of a For Each...Next loop starts, Visual Basic verifies that group refers to a valid collection object. Si no es así, se produce una excepción.If not, it throws an exception. De lo contrario, llama al método MoveNext y a la propiedad Current del objeto enumerador para devolver el primer elemento.Otherwise, it calls the MoveNext method and the Current property of the enumerator object to return the first element. Si MoveNext indica que no hay ningún elemento siguiente, es decir, si la colección está vacía, el bucle For Each se detiene y el control pasa a la instrucción que sigue a la instrucción Next.If MoveNext indicates that there is no next element, that is, if the collection is empty, the For Each loop stops and control passes to the statement following the Next statement. De lo contrario, Visual Basic establece element en el primer elemento y ejecuta el bloque de instrucciones.Otherwise, Visual Basic sets element to the first element and runs the statement block.

Cada vez que Visual Basic encuentra la instrucción Next, vuelve a la instrucción For Each.Each time Visual Basic encounters the Next statement, it returns to the For Each statement. Una vez más, llama a MoveNext y Current para devolver el siguiente elemento y, de nuevo, ejecuta el bloque o detiene el bucle en función del resultado.Again it calls MoveNext and Current to return the next element, and again it either runs the block or stops the loop depending on the result. Este proceso continúa hasta que MoveNext indica que no hay ningún elemento siguiente o se encuentra una instrucción Exit For.This process continues until MoveNext indicates that there is no next element or an Exit For statement is encountered.

Modificar la colección.Modifying the Collection. El objeto de enumerador devuelto por GetEnumerator normalmente no permite cambiar la colección agregando, eliminando, reemplazando o reordenando los elementos.The enumerator object returned by GetEnumerator normally doesn't let you change the collection by adding, deleting, replacing, or reordering any elements. Si cambia la colección después de haber iniciado un bucle For Each... Next, el objeto de enumerador deja de ser válido y el siguiente intento de obtener acceso a un elemento produce una excepción @no__t 2.If you change the collection after you have initiated a For Each...Next loop, the enumerator object becomes invalid, and the next attempt to access an element causes an InvalidOperationException exception.

Sin embargo, este bloqueo de modificación no viene determinado por Visual Basic, sino por la implementación de la interfaz IEnumerable.However, this blocking of modification isn't determined by Visual Basic, but rather by the implementation of the IEnumerable interface. Es posible implementar IEnumerable de forma que permita la modificación durante la iteración.It is possible to implement IEnumerable in a way that allows for modification during iteration. Si está pensando en realizar esta modificación dinámica, asegúrese de que comprende las características de la implementación IEnumerable en la colección que está utilizando.If you are considering doing such dynamic modification, make sure that you understand the characteristics of the IEnumerable implementation on the collection you are using.

Modificar elementos de la colección.Modifying Collection Elements. La propiedad Current del objeto enumerador es de solo lecturay devuelve una copia local de cada elemento de la colección.The Current property of the enumerator object is ReadOnly, and it returns a local copy of each collection element. Esto significa que no se pueden modificar los propios elementos en un bucle For Each... Next.This means that you cannot modify the elements themselves in a For Each...Next loop. Cualquier modificación que realice solo afectará a la copia local de Current y no se reflejará de nuevo en la colección subyacente.Any modification you make affects only the local copy from Current and isn't reflected back into the underlying collection. Sin embargo, si un elemento es un tipo de referencia, puede modificar los miembros de la instancia a la que señala.However, if an element is a reference type, you can modify the members of the instance to which it points. En el ejemplo siguiente se modifica el miembro BackColor de cada elemento thisControl.The following example modifies the BackColor member of each thisControl element. Sin embargo, no puede modificar thisControl.You cannot, however, modify thisControl itself.

Sub LightBlueBackground(thisForm As System.Windows.Forms.Form)
    For Each thisControl In thisForm.Controls
        thisControl.BackColor = System.Drawing.Color.LightBlue
    Next thisControl
End Sub

En el ejemplo anterior se puede modificar el miembro BackColor de cada elemento thisControl, aunque no se puede modificar @no__t 2.The previous example can modify the BackColor member of each thisControl element, although it cannot modify thisControl itself.

Atravesar matrices.Traversing Arrays. Dado que la clase Array implementa la interfaz IEnumerable, todas las matrices exponen el método GetEnumerator.Because the Array class implements the IEnumerable interface, all arrays expose the GetEnumerator method. Esto significa que puede recorrer en iteración una matriz con un bucle For Each... Next.This means that you can iterate through an array with a For Each...Next loop. Sin embargo, solo puede leer los elementos de la matriz.However, you can only read the array elements. No se pueden cambiar.You cannot change them.

EjemploExample

En el ejemplo siguiente se enumeran todas las carpetas de C:\ mediante el uso de la clase DirectoryInfo.The following example lists all the folders in the C:\ directory by using the DirectoryInfo class.

Dim dInfo As New System.IO.DirectoryInfo("c:\")
For Each dir As System.IO.DirectoryInfo In dInfo.GetDirectories()
    Debug.WriteLine(dir.Name)
Next

EjemploExample

En el ejemplo siguiente se muestra un procedimiento para ordenar una colección.The following example illustrates a procedure for sorting a collection. El ejemplo ordena las instancias de una clase Car que se almacenan en un List<T>.The example sorts instances of a Car class that are stored in a List<T>. La clase Car implementa la interfaz IComparable<T>, que requiere implementar el método CompareTo.The Car class implements the IComparable<T> interface, which requires that the CompareTo method be implemented.

Cada llamada al método CompareTo realiza una comparación única que se usa para la ordenación.Each call to the CompareTo method makes a single comparison that's used for sorting. El código escrito por el usuario en el método CompareTo devuelve un valor para cada comparación del objeto actual con otro objeto.User-written code in the CompareTo method returns a value for each comparison of the current object with another object. El valor devuelto es menor que cero si el objeto actual es menor que el otro objeto, mayor que cero si el objeto actual es mayor que el otro objeto y cero si son iguales.The value returned is less than zero if the current object is less than the other object, greater than zero if the current object is greater than the other object, and zero if they are equal. Esto permite definir en el código los criterios de mayor que, menor que e igual.This enables you to define in code the criteria for greater than, less than, and equal.

En el método ListCars, la instrucción cars.Sort() ordena la lista.In the ListCars method, the cars.Sort() statement sorts the list. Esta llamada al método Sort de List<T> hace que se llame automáticamente al método CompareTo para los objetos Car de List.This call to the Sort method of the List<T> causes the CompareTo method to be called automatically for the Car objects in the List.

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

Vea tambiénSee also