Instrução For Each...Next (Visual Basic)For Each...Next Statement (Visual Basic)

Repete um grupo de instruções para cada elemento em uma coleção.Repeats a group of statements for each element in a collection.

SintaxeSyntax

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

PartesParts

TermoTerm DefiniçãoDefinition
element Necessário na instrução For Each.Required in the For Each statement. Opcional na instrução Next.Optional in the Next statement. Ela.Variable. Usado para iterar pelos elementos da coleção.Used to iterate through the elements of the collection.
datatype Opcional se Option Infer estiver on (o padrão) ou element já estiver declarado; obrigatório se Option Infer estiver off e element já não estiver declarado.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. O tipo de dados de element.The data type of element.
group Necessário.Required. Uma variável com um tipo que é um tipo de coleção ou objeto.A variable with a type that's a collection type or Object. Refere-se à coleção sobre a qual o statements deve ser repetido.Refers to the collection over which the statements are to be repeated.
statements Opcional.Optional. Uma ou mais instruções entre For Each e Next que são executados em cada item em group.One or more statements between For Each and Next that run on each item in group.
Continue For Opcional.Optional. Transfere o controle para o início do loop For Each.Transfers control to the start of the For Each loop.
Exit For Opcional.Optional. Transfere o controle do loop For Each.Transfers control out of the For Each loop.
Next Necessário.Required. Encerra a definição do loop For Each.Terminates the definition of the For Each loop.

Exemplo simplesSimple Example

Use um loop For Each... Next quando desejar repetir um conjunto de instruções para cada elemento de uma coleção ou matriz.Use a For Each...Next loop when you want to repeat a set of statements for each element of a collection or array.

Dica

Um para... A próxima instrução funciona bem quando você pode associar cada iteração de um loop a uma variável de controle e determinar os valores iniciais e finais da variável.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. No entanto, quando você está lidando com uma coleção, o conceito de valores iniciais e finais não é significativo e você não sabe necessariamente quantos elementos a coleção tem.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. Nesse tipo de caso, um loop For Each... Next é geralmente uma opção melhor.In this kind of case, a For Each...Next loop is often a better choice.

No exemplo a seguir, o For Each... NextIn the following example, the For EachNext a instrução faz a iteração por todos os elementos de uma coleção 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 obter mais exemplos, consulte coleções e matrizes.For more examples, see Collections and Arrays.

Loops aninhadosNested Loops

Você pode aninhar loops For Each colocando um loop dentro de outro.You can nest For Each loops by putting one loop within another.

O exemplo a seguir demonstra For Each aninhados... NextThe following example demonstrates nested For EachNext estruturas.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 

Quando você Aninha loops, cada loop deve ter uma variável element exclusiva.When you nest loops, each loop must have a unique element variable.

Você também pode aninhar diferentes tipos de estruturas de controle entre si.You can also nest different kinds of control structures within each other. Para obter mais informações, consulte estruturas de controle aninhado.For more information, see Nested Control Structures.

Sair para e continuar paraExit For and Continue For

A instrução Exit for faz com que a execução saia do For... NextThe Exit For statement causes execution to exit the ForNext loop e transfere o controle para a instrução que segue a instrução Next.loop and transfers control to the statement that follows the Next statement.

A instrução Continue For transfere o controle imediatamente para a próxima iteração do loop.The Continue For statement transfers control immediately to the next iteration of the loop. Para obter mais informações, consulte instrução Continue.For more information, see Continue Statement.

O exemplo a seguir mostra como usar as instruções Continue For e 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

Você pode colocar qualquer número de instruções Exit For em um loop For Each.You can put any number of Exit For statements in a For Each loop. Quando usado em loops For Each aninhados, Exit For faz com que a execução saia do loop mais interno e transfere o controle para o próximo nível mais alto de aninhamento.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.

o Exit For geralmente é usado após uma avaliação de alguma condição, por exemplo, em uma estrutura If... Then... Else.Exit For is often used after an evaluation of some condition, for example, in an If...Then...Else structure. Talvez você queira usar Exit For para as seguintes condições:You might want to use Exit For for the following conditions:

  • Continuar a iterar é desnecessário ou impossível.Continuing to iterate is unnecessary or impossible. Isso pode ser causado por um valor errado ou uma solicitação de encerramento.This might be caused by an erroneous value or a termination request.

  • Uma exceção é capturada em um Try... Catch... Finally. Você pode usar Exit For no final do bloco Finally.An exception is caught in a Try...Catch...Finally. You might use Exit For at the end of the Finally block.

  • Há um loop infinito, que é um loop que poderia executar um número grande ou uniforme de vezes infinito.There an endless loop, which is a loop that could run a large or even infinite number of times. Se você detectar essa condição, poderá usar Exit For para escapar do loop.If you detect such a condition, you can use Exit For to escape the loop. Para obter mais informações, consulte do... Instrução loop.For more information, see Do...Loop Statement.

IteratorsIterators

Você usa um iterador para executar uma iteração personalizada em uma coleção.You use an iterator to perform a custom iteration over a collection. Um iterador pode ser uma função ou um acessador Get.An iterator can be a function or a Get accessor. Ele usa uma instrução Yield para retornar cada elemento da coleção um de cada vez.It uses a Yield statement to return each element of the collection one at a time.

Você chama um iterador usando uma instrução For Each...Next.You call an iterator by using a For Each...Next statement. Cada iteração do loop For Each chama o iterador.Each iteration of the For Each loop calls the iterator. Quando uma instrução Yield é atingida no iterador, a expressão na instrução Yield é retornada e o local atual no código é retido.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. A execução será reiniciada desse local na próxima vez que o iterador for chamado.Execution is restarted from that location the next time that the iterator is called.

O exemplo a seguir usa uma função de iterador.The following example uses an iterator function. A função Iterator tem uma instrução Yield que está dentro de um para... Próximo loop.The iterator function has a Yield statement that's inside a For…Next loop. No método ListEvenNumbers, cada iteração do corpo da instrução For Each cria uma chamada para a função de iterador, que prossegue para a próxima instrução 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 obter mais informações, consulte iteradores, instrução yielde iterador.For more information, see Iterators, Yield Statement, and Iterator.

Implementação TécnicaTechnical Implementation

Quando um For Each... NextWhen a For EachNext a instrução é executada, Visual Basic avalia a coleção somente uma vez, antes de o loop ser iniciado.statement runs, Visual Basic evaluates the collection only one time, before the loop starts. Se a instrução bloquear alterações element ou group, essas alterações não afetarão a iteração do loop.If your statement block changes element or group, these changes don't affect the iteration of the loop.

Quando todos os elementos na coleção tiverem sido atribuídos sucessivamente a element, o loop For Each será interrompido e o controle passará para a instrução após a instrução 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.

Se Option Infer estiver on (sua configuração padrão), o compilador Visual Basic poderá inferir o tipo de dados de element.If Option Infer is on (its default setting), the Visual Basic compiler can infer the data type of element. Se ele estiver desativado e element não tiver sido declarado fora do loop, você deverá declará-lo na instrução 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 o tipo de dados de element explicitamente, use uma cláusula As.To declare the data type of element explicitly, use an As clause. A menos que o tipo de dados do elemento seja definido fora da construção For Each... Next, seu escopo será o corpo do loop.Unless the data type of element is defined outside the For Each...Next construct, its scope is the body of the loop. Observe que você não pode declarar element fora e dentro do loop.Note that you cannot declare element both outside and inside the loop.

Opcionalmente, você pode especificar element na instrução Next.You can optionally specify element in the Next statement. Isso melhora a legibilidade do seu programa, especialmente se você tiver aninhado loops For Each.This improves the readability of your program, especially if you have nested For Each loops. Você deve especificar a mesma variável como aquela que aparece na instrução For Each correspondente.You must specify the same variable as the one that appears in the corresponding For Each statement.

Talvez você queira evitar alterar o valor de element dentro de um loop.You might want to avoid changing the value of element inside a loop. Fazer isso pode dificultar a leitura e a depuração do código.Doing this can make it more difficult to read and debug your code. Alterar o valor de group não afeta a coleção ou seus elementos, que foram determinados quando o loop foi inserido pela primeira vez.Changing the value of group doesn't affect the collection or its elements, which were determined when the loop was first entered.

Quando você estiver aninhando loops, se uma instrução Next de um nível de aninhamento externo for encontrada antes da Next de um nível interno, o compilador sinalizará um erro.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. No entanto, o compilador pode detectar esse erro sobreposto somente se você especificar element em cada instrução Next.However, the compiler can detect this overlapping error only if you specify element in every Next statement.

Se o seu código depende de percorrer uma coleção em uma ordem específica, um loop For Each... Next não é a melhor opção, a menos que você saiba as características do objeto enumerador que a coleção expõe.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. A ordem de passagem não é determinada por Visual Basic, mas pelo método MoveNext do objeto enumerador.The order of traversal isn't determined by Visual Basic, but by the MoveNext method of the enumerator object. Portanto, talvez você não consiga prever qual elemento da coleção é o primeiro a ser retornado em element, ou que é o próximo a ser retornado após um determinado elemento.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. Você pode obter resultados mais confiáveis usando uma estrutura de loop diferente, como For... Next ou Do... Loop.You might achieve more reliable results using a different loop structure, such as For...Next or Do...Loop.

O tempo de execução deve ser capaz de converter os elementos em group em element.The runtime must be able to convert the elements in group to element. A instrução [Option Strict] controla se as conversões de alargamento e de estreitamento são permitidas (Option Strict está desativado, seu valor padrão) ou se apenas conversões ampliadas são permitidas (Option Strict está ativado).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 obter mais informações, consulte conversões redutoras.For more information, see Narrowing conversions.

O tipo de dados de group deve ser um tipo de referência que se refere a uma coleção ou uma matriz enumerável.The data type of group must be a reference type that refers to a collection or an array that's enumerable. Normalmente, isso significa que group se refere a um objeto que implementa a interface IEnumerable do namespace System.Collections ou a interface IEnumerable<T> do namespace 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 o método GetEnumerator, que retorna um objeto enumerador para a coleção.System.Collections.IEnumerable defines the GetEnumerator method, which returns an enumerator object for the collection. O objeto Enumerator implementa a interface System.Collections.IEnumerator do namespace System.Collections e expõe a propriedade Current e os métodos Reset e 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 os usa para atravessar a coleção.Visual Basic uses these to traverse the collection.

Conversões de reduçãoNarrowing Conversions

Quando Option Strict é definido como On, as conversões redutoras normalmente causam erros do compilador.When Option Strict is set to On, narrowing conversions ordinarily cause compiler errors. No entanto, em uma instrução For Each, as conversões dos elementos em group a element são avaliadas e executadas em tempo de execução, e os erros do compilador causados por conversões de restrição são suprimidos.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.

No exemplo a seguir, a atribuição de m como o valor inicial para n não é compilada quando Option Strict está on porque a conversão de um Long em um Integer é uma conversão de restrição.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. No entanto, na instrução For Each, nenhum erro do compilador é relatado, mesmo que a atribuição a number exija a mesma conversão de Long para 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. Na instrução For Each que contém um número grande, ocorre um erro em tempo de execução quando ToInteger é aplicado ao 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

Chamadas de IEnumeratorIEnumerator Calls

Quando a execução de um loop For Each... Next é iniciada, Visual Basic verifica se group refere-se a um objeto de coleção válido.When execution of a For Each...Next loop starts, Visual Basic verifies that group refers to a valid collection object. Caso contrário, ele gera uma exceção.If not, it throws an exception. Caso contrário, ele chama o método MoveNext e a propriedade Current do objeto enumerador para retornar o primeiro elemento.Otherwise, it calls the MoveNext method and the Current property of the enumerator object to return the first element. Se MoveNext indicar que não há nenhum elemento seguinte, ou seja, se a coleção estiver vazia, o loop For Each será interrompido e o controle passará para a instrução após a instrução 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. Caso contrário, Visual Basic define element para o primeiro elemento e executa o bloco de instruções.Otherwise, Visual Basic sets element to the first element and runs the statement block.

Cada vez que Visual Basic encontra a instrução Next, ele retorna à instrução For Each.Each time Visual Basic encounters the Next statement, it returns to the For Each statement. Novamente, ele chama MoveNext e Current para retornar o próximo elemento e, novamente, ele executa o bloco ou interrompe o loop dependendo do 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. Esse processo continua até que MoveNext indique que não há nenhum elemento seguinte ou uma instrução Exit For é encontrada.This process continues until MoveNext indicates that there is no next element or an Exit For statement is encountered.

Modificando a coleção.Modifying the Collection. O objeto enumerador retornado pelo GetEnumerator normalmente não permite que você altere a coleção adicionando, excluindo, substituindo ou reordenando quaisquer elementos.The enumerator object returned by GetEnumerator normally doesn't let you change the collection by adding, deleting, replacing, or reordering any elements. Se você alterar a coleção depois de iniciar um loop For Each... Next, o objeto enumerador se tornará inválido e a próxima tentativa de acessar um elemento causará uma exceção InvalidOperationException.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.

No entanto, esse bloqueio de modificação não é determinado pelo Visual Basic, mas sim pela implementação da interface IEnumerable.However, this blocking of modification isn't determined by Visual Basic, but rather by the implementation of the IEnumerable interface. É possível implementar IEnumerable de uma maneira que permita modificações durante a iteração.It is possible to implement IEnumerable in a way that allows for modification during iteration. Se estiver pensando em fazer essa modificação dinâmica, certifique-se de entender as características da implementação IEnumerable na coleção que você 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.

Modificando elementos de coleção.Modifying Collection Elements. A propriedade Current do objeto enumerador é ReadOnlye retorna uma cópia local de cada elemento da coleção.The Current property of the enumerator object is ReadOnly, and it returns a local copy of each collection element. Isso significa que você não pode modificar os elementos em um loop For Each... Next.This means that you cannot modify the elements themselves in a For Each...Next loop. Qualquer modificação que você faça afeta apenas a cópia local de Current e não é refletida de volta para a coleção subjacente.Any modification you make affects only the local copy from Current and isn't reflected back into the underlying collection. No entanto, se um elemento for um tipo de referência, você poderá modificar os membros da instância para a qual ele aponta.However, if an element is a reference type, you can modify the members of the instance to which it points. O exemplo a seguir modifica o membro BackColor de cada elemento thisControl.The following example modifies the BackColor member of each thisControl element. No entanto, você não pode modificar o thisControl em si.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

O exemplo anterior pode modificar o membro BackColor de cada elemento thisControl, embora ele não possa modificar o próprio thisControl.The previous example can modify the BackColor member of each thisControl element, although it cannot modify thisControl itself.

Atravessando matrizes.Traversing Arrays. Como a classe Array implementa a interface IEnumerable, todas as matrizes expõem o método GetEnumerator.Because the Array class implements the IEnumerable interface, all arrays expose the GetEnumerator method. Isso significa que você pode iterar por meio de uma matriz com um loop For Each... Next.This means that you can iterate through an array with a For Each...Next loop. No entanto, você só pode ler os elementos da matriz.However, you can only read the array elements. Você não pode alterá-los.You cannot change them.

ExemploExample

O exemplo a seguir lista todas as pastas em C:\ diretório usando a classe 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

ExemploExample

O exemplo a seguir ilustra um procedimento para a classificação de uma coleção.The following example illustrates a procedure for sorting a collection. O exemplo classifica instâncias de uma classe Car que são armazenadas em um List<T>.The example sorts instances of a Car class that are stored in a List<T>. A classe Car implementa a interface IComparable<T>, que requer que o método CompareTo seja implementado.The Car class implements the IComparable<T> interface, which requires that the CompareTo method be implemented.

Cada chamada para o método CompareTo faz uma única comparação que é usada para classificação.Each call to the CompareTo method makes a single comparison that's used for sorting. Os códigos escritos pelo usuário no método CompareTo retornam um valor para cada comparação do objeto atual com outro objeto.User-written code in the CompareTo method returns a value for each comparison of the current object with another object. O valor retornado será menor que zero se o objeto atual for menor que o outro objeto, maior que zero se o objeto atual for maior que o outro objeto e zero, se eles forem iguais.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. Isso permite que você defina no código os critérios para maior que, menor que e igual.This enables you to define in code the criteria for greater than, less than, and equal.

No método ListCars, a instrução cars.Sort() classifica a lista.In the ListCars method, the cars.Sort() statement sorts the list. Essa chamada para o método Sort da List<T> faz com que o método CompareTo seja chamado automaticamente para os objetos Car na 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

Consulte tambémSee also