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 For Each instrucción.Required in the For Each statement. Opcional en la Next instrucción.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 está activado (valor predeterminado) o element ya se ha declarado; obligatorio Option Infer si es OFF element y 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 Necesario.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 statements que se van a repetir.Refers to the collection over which the statements are to be repeated.
statements Opcional.Optional. Una o más instrucciones entre For Each y Next que se ejecutan en cada groupelemento de.One or more statements between For Each and Next that run on each item in group.
Continue For Opcional.Optional. Transfiere el control al inicio del For Each bucle.Transfers control to the start of the For Each loop.
Exit For Opcional.Optional. Transfiere el For Each control fuera del bucle.Transfers control out of the For Each loop.
Next Necesario.Required. Finaliza la definición del For Each bucle.Terminates the definition of the For Each loop.

Ejemplo sencilloSimple Example

For EachUsar... Next bucle cuando se desea 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, For Each... Next el bucle suele ser una opción mejor.In this kind of case, a For Each...Next loop is often a better choice.

En el ejemplo siguiente, 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 For Each bucles colocando un bucle dentro de otro.You can nest For Each loops by putting one loop within another.

En el siguiente ejemplo se muestra For Eachla instrucción anidada...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 Forde...NextThe Exit For statement causes execution to exit the ForNext bucle y transfiere el control a la instrucción que sigue Next a la instrucción.loop and transfers control to the statement that follows the Next statement.

La Continue For instrucción 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 Continue For las Exit For instrucciones y.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 Exit For instrucciones en un For Each bucle.You can put any number of Exit For statements in a For Each loop. Cuando se usa dentro de For Each bucles 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 Forse suele usar después de una evaluación de alguna condición, por ejemplo, en If... Then... Else estructura.Exit For is often used after an evaluation of some condition, for example, in an If...Then...Else structure. Puede 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 detecta una excepción en Try... Catch... Finally. Puede usar Exit For al final Finally del bloque.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 Get un descriptor de acceso.An iterator can be a function or a Get accessor. Usa una Yield instrucción 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 For Each...Next una instrucción.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 Yield alcanza una instrucción en el iterador, se devuelve la Yield expresión de la instrucción 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 Yield tiene una instrucción que está dentro de un ... Siguiente bucle.The iterator function has a Yield statement that's inside a For…Next loop. En el ListEvenNumbers método, cada iteración del For Each cuerpo de la instrucción crea una llamada a la función de iterador, que continúa Yield con la siguiente instrucción.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

For EachCuando...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 element cambia groupo, 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 For Each bucle se detiene y el control pasa a la instrucción Next que sigue a la instrucción.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 elementtipo de datos de.If Option Infer is on (its default setting), the Visual Basic compiler can infer the data type of element. Si está desactivado element y no se ha declarado fuera del bucle, debe declararlo For Each en la instrucción.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 element de explícitamente, As use una cláusula.To declare the data type of element explicitly, use an As clause. A menos que el tipo de datos del elemento se For Eachdefina fuera de... 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 element puede declarar fuera y dentro del bucle.Note that you cannot declare element both outside and inside the loop.

Opcionalmente, puede especificar element en la Next instrucción.You can optionally specify element in the Next statement. Esto mejora la legibilidad del programa, sobre todo si tiene For Each bucles 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 correspondiente For Each .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 dentro element 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 o 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 Next instrucción de un nivel de anidamiento externo antes de la 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 element solo si Next especifica en cada instrucción.However, the compiler can detect this overlapping error only if you specify element in every Next statement.

Si el código depende del recorrido de una colección en un orden determinado, For Each... Next el bucle 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 por el MoveNext método 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 cuál 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, Forcomo... Next oDo... 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 group elementos elementde en.The runtime must be able to convert the elements in group to element. La instrucciónOption 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 (Option Strict 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 group de 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. group Normalmente esto significa que hace referencia a un objeto que implementa la IEnumerable interfaz del System.Collections espacio de nombres o la IEnumerable<T> interfaz del System.Collections.Generic espacio de nombres.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.IEnumerabledefine el GetEnumerator método, 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. System.Collections.IEnumerator El objeto Current Reset de enumerador implementa la interfaz MoveNext del espaciodenombresyexponelapropiedadylosmétodosy.System.CollectionsThe 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 For Each , en una instrucción, las conversiones de los elementos group element de en se evalúan y se ejecutan 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 Option Strict cuando es Integer on porque la conversión de Long un en 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. En la For Each instrucción, sin embargo, no se muestra ningún error del compilador, number aunque la asignación a requiere Long la Integermisma conversión de a.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 For Each instrucción que contiene un número grande, se produce un error en tiempo de ToInteger ejecución cuando se aplica 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

Al ejecutar un For Each... se inicia el bucle, Visual Basic comprueba group que hace referencia a un objeto de colección válido. NextWhen 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 MoveNext al método y Current a la propiedad del objeto de 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 For Each bucle se detiene y el control pasa a la instrucción Next que sigue a la instrucción.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, element Visual Basic establece 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 Next instrucción, devuelve a la For Each instrucción.Each time Visual Basic encounters the Next statement, it returns to the For Each statement. Una vez más MoveNext , Current llama a y 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 MoveNext que indica que no hay ningún elemento siguiente o Exit For se encuentra una instrucción.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 GetEnumerator devuelto por 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 una For Each... , el objeto de enumerador deja de ser válido y el siguiente intento de obtener acceso a InvalidOperationException un elemento produce una excepción. NextIf 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 IEnumerable la interfaz.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 IEnumerable implementación en la colección que está usando.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 Current propiedad 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 For Eachuna... Next bucle.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 Current local de y no se reflejará 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 BackColor el miembro de thisControl cada elemento.The following example modifies the BackColor member of each thisControl element. Sin embargo, no puede modificarse thisControl a sí mismo.You cannot, however, modify thisControl itself.

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

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

Atravesar matrices.Traversing Arrays. Dado que Array la clase implementa la IEnumerable interfaz, todas las matrices exponen el GetEnumerator método.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 For Each... Next bucle.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:\ directorio mediante la DirectoryInfo clase.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 Car una clase que se almacenan List<T>en un.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