Оператор For Each...Next (Visual Basic)For Each...Next Statement (Visual Basic)

Повторяет группу операторов для каждого элемента в коллекции.Repeats a group of statements for each element in a collection.

СинтаксисSyntax

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

ЧастиParts

ТерминTerm ОпределениеDefinition
element Требуется в For Each инструкции.Required in the For Each statement. Необязательно в Next инструкции.Optional in the Next statement. переменная.Variable. Используется для итерации по элементам коллекции.Used to iterate through the elements of the collection.
datatype Необязателен при Option Infer (по умолчанию) или element уже объявлено; требуется, если Option Infer отключен и element уже не объявлен.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. Тип данных element.The data type of element.
group Обязательный.Required. Переменная с типом, который является типом коллекции или объект.A variable with a type that's a collection type or Object. Ссылается на коллекцию, по которому statements будут повторяться.Refers to the collection over which the statements are to be repeated.
statements Необязательный параметр.Optional. Один или несколько операторов между For Each и Next , выполните на каждом элементе в group.One or more statements between For Each and Next that run on each item in group.
Continue For Необязательный параметр.Optional. Передает управление в начало For Each цикла.Transfers control to the start of the For Each loop.
Exit For Необязательный параметр.Optional. Передает управление из For Each цикла.Transfers control out of the For Each loop.
Next Обязательный.Required. Завершает определение For Each цикла.Terminates the definition of the For Each loop.

Простой примерSimple Example

Используйте For Each... Next цикл, когда нужно повторить набор инструкций для каждого элемента коллекции или массиве.Use a For Each...Next loop when you want to repeat a set of statements for each element of a collection or array.

Совет

Объект для... Следующий оператор работает хорошо, когда вы можете связать каждой итерации цикла с управляющей переменной и определить начальное и конечное значения этой переменной.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. Тем не менее при работе с коллекцией, концепция начальное и конечное значения лишено смысла и не требуется знать количество элементов, коллекция имеет.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. В таком случае For Each... Next цикл часто является наиболее предпочтительной.In this kind of case, a For Each...Next loop is often a better choice.

В следующем примере For Each...NextIn the following example, the For EachNext оператор используется для итерации по все элементы коллекции-списка.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

Дополнительные примеры см. в разделе коллекций и массивы.For more examples, see Collections and Arrays.

Вложенные циклыNested Loops

Можно вложить For Each циклы, поместив в одном цикле в другую.You can nest For Each loops by putting one loop within another.

В следующем примере демонстрируется вложенных For Each...NextThe following example demonstrates nested For EachNext структуры.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 

При вложении циклы, каждый цикл должен иметь уникальный element переменной.When you nest loops, each loop must have a unique element variable.

Можно также вложить разные виды структур управления друг с другом.You can also nest different kinds of control structures within each other. Дополнительные сведения см. в разделе вложенные структуры управления.For more information, see Nested Control Structures.

Возврата для и продолжите дляExit For and Continue For

Выхода для инструкция вызывает выполнение выйти из For...NextThe Exit For statement causes execution to exit the ForNext цикл передает управление оператору, который расположен Next инструкции.loop and transfers control to the statement that follows the Next statement.

Continue For Оператор передает управление непосредственно в следующую итерацию цикла.The Continue For statement transfers control immediately to the next iteration of the loop. Дополнительные сведения см. в разделе оператор Continue.For more information, see Continue Statement.

В следующем примере показано, как использовать Continue For и 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

Можно поместить любое количество Exit For инструкций в For Each цикла.You can put any number of Exit For statements in a For Each loop. При использовании внутри вложенной For Each циклы, Exit For выполнение выйти из самого внутреннего цикла передает управление на следующий уровень вложенности.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 часто используется после оценки некоторого условия, например, в If... Then... Else структуры.Exit For is often used after an evaluation of some condition, for example, in an If...Then...Else structure. Вы можете использовать Exit For для следующих условий:You might want to use Exit For for the following conditions:

  • Продолжение для выполнения итерации, ненужных или невозможно.Continuing to iterate is unnecessary or impossible. Это может быть вызвано ошибочное значение или запрос на завершение.This might be caused by an erroneous value or a termination request.

  • Исключение перехватывается в Try... Catch... Finally. Можно использовать Exit For в конце Finally блока.An exception is caught in a Try...Catch...Finally. You might use Exit For at the end of the Finally block.

  • Там бесконечный цикл, который является цикл, который может запустить большое или возможно, бесконечное число раз.There an endless loop, which is a loop that could run a large or even infinite number of times. При обнаружении таких условий, можно использовать Exit For для выхода из цикла.If you detect such a condition, you can use Exit For to escape the loop. Дополнительные сведения см. в разделе сделать... Цикл инструкции.For more information, see Do...Loop Statement.

ИтераторыIterators

Использовании итератор для выполнения настраиваемого перебора коллекции.You use an iterator to perform a custom iteration over a collection. Итератор, который может быть функцией или Get метода доступа.An iterator can be a function or a Get accessor. Она использует Yield инструкцию для возврата всех элементов коллекции по одному за раз.It uses a Yield statement to return each element of the collection one at a time.

Итератор вызывается с помощью For Each...Next инструкции.You call an iterator by using a For Each...Next statement. Каждая итерация цикла For Each вызывает итератор.Each iteration of the For Each loop calls the iterator. Когда Yield в итераторе, выражение в достижении оператора Yield инструкции возвращается и сохраняется текущее расположение в коде.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. При следующем вызове итератора выполнение возобновляется с этого места.Execution is restarted from that location the next time that the iterator is called.

Следующий пример использует функцию итератора.The following example uses an iterator function. Имеет функции итератора Yield инструкцию, которая находится внутри для... Далее цикла.The iterator function has a Yield statement that's inside a For…Next loop. В ListEvenNumbers метод, каждая итерация For Each тела оператора создает вызов функции итератора, который переходит к следующему 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

Дополнительные сведения см. в разделе итераторы, оператор Yield, и итератор.For more information, see Iterators, Yield Statement, and Iterator.

Техническая реализацияTechnical Implementation

Когда For Each...NextWhen a For EachNext Инструкция переходит, Visual Basic анализирует всю коллекцию только один раз, перед началом цикла.statement runs, Visual Basic evaluates the collection only one time, before the loop starts. Если в блоке операторов изменяется element или group, эти изменения не влияют на итерации цикла.If your statement block changes element or group, these changes don't affect the iteration of the loop.

Когда все элементы в коллекции, можно последовательно назначенные element, For Each цикл останавливается и управление передается оператору, следующему 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.

Если Option Infer является (Настройка его по умолчанию), компилятор Visual Basic может вывести тип данных element.If Option Infer is on (its default setting), the Visual Basic compiler can infer the data type of element. Если он выключен и element еще не был объявлен вне цикла, необходимо объявить ее в For Each инструкции.If it is off and element hasn't been declared outside the loop, you must declare it in the For Each statement. Чтобы объявить тип данных element явно, используйте As предложение.To declare the data type of element explicitly, use an As clause. Если тип данных элемента определен вне данного For Each... Next конструкция, его область представляет собой тело цикла.Unless the data type of element is defined outside the For Each...Next construct, its scope is the body of the loop. Обратите внимание, что нельзя объявлять element и снаружи цикла.Note that you cannot declare element both outside and inside the loop.

При необходимости можно указать element в Next инструкции.You can optionally specify element in the Next statement. Это повышает удобочитаемость программы, особенно в том случае, если имеются вложенные For Each циклы.This improves the readability of your program, especially if you have nested For Each loops. Необходимо указать ту же переменную, что отображается в соответствующем For Each инструкции.You must specify the same variable as the one that appears in the corresponding For Each statement.

Может потребоваться не следует изменять значение element внутри цикла.You might want to avoid changing the value of element inside a loop. Это может затруднить его для чтения и отладки кода.Doing this can make it more difficult to read and debug your code. Изменение значения group не влияет на коллекции или ее элементы, которые были определены при цикла.Changing the value of group doesn't affect the collection or its elements, which were determined when the loop was first entered.

Когда вложенные циклы, если Next внешнего уровня вложенности встречается перед Next внутреннего уровня, компилятор сообщает об ошибке.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. Тем не менее, компилятор может определить, это перекрытие ошибки только в том случае, если указать element в каждом Next инструкции.However, the compiler can detect this overlapping error only if you specify element in every Next statement.

Если код исходит обхода коллекции в определенном порядке, For Each... Next цикл не лучшим выбором, если вы не знаете характеристики объекта-перечислителя коллекции представляет.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, а от MoveNext метод объекта перечислителя.The order of traversal isn't determined by Visual Basic, but by the MoveNext method of the enumerator object. Таким образом, вы не сможете прогнозировать, какой элемент коллекции является первым должен быть возвращен в element, или это Далее возвращается после заданного элемента.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. Можно достичь более надежных результатов с помощью другой циклической структуры, например For... Next или Do... Loop.You might achieve more reliable results using a different loop structure, such as For...Next or Do...Loop.

Среда выполнения должна быть возможность преобразовать элементы в group для element.The runtime must be able to convert the elements in group to element. [Option Strict] Инструкция определяет, разрешено ли расширяющих и сужающих преобразований (Option Strict выключен, его значение по умолчанию), или, разрешена ли только расширяющие преобразования (Option Strict включен).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). Дополнительные сведения см. в разделе сужающие преобразования.For more information, see Narrowing conversions.

Тип данных group должен быть ссылочного типа, который ссылается на коллекцию или массив, который является перечислимым.The data type of group must be a reference type that refers to a collection or an array that's enumerable. Чаще всего это означает, что group ссылается на объект, реализующий IEnumerable интерфейс System.Collections пространства имен или IEnumerable<T> интерфейс 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 Определяет GetEnumerator метод, который возвращает объект перечислителя для коллекции.System.Collections.IEnumerable defines the GetEnumerator method, which returns an enumerator object for the collection. Реализует объект перечислителя System.Collections.IEnumerator интерфейс System.Collections пространства имен и предоставляет Current свойство и Reset и 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 использует их для перемещения по коллекции.Visual Basic uses these to traverse the collection.

сужающие преобразованияNarrowing Conversions

Когда Option Strict присваивается On, сужающее преобразование обычно вызывает ошибки компилятора.When Option Strict is set to On, narrowing conversions ordinarily cause compiler errors. В For Each инструкции, тем не менее, преобразования из элементов в group для element вычисляются и во время выполнения и ошибки компилятора, из-за сужающие преобразования подавляются.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.

В следующем примере, назначение m как начальное значение для n не будет компилироваться при Option Strict включен, так как преобразование Long для Integer является сужающим преобразованием.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. В For Each инструкции, однако никакие ошибки компилятора не сообщается, даже если назначения number требуется то же самое преобразование из Long для 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. В For Each инструкцию, которая содержит множество, то во время выполнения возникает ошибка при ToInteger применяется к большим числом.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

IEnumerator вызововIEnumerator Calls

При выполнении For Each... Next начале цикла, Visual Basic проверяет, что group ссылается на объект допустимую коллекцию.When execution of a For Each...Next loop starts, Visual Basic verifies that group refers to a valid collection object. В противном случае создается исключение.If not, it throws an exception. В противном случае он вызывает MoveNext метод и Current свойство объекта перечислителя для возвращения первого элемента.Otherwise, it calls the MoveNext method and the Current property of the enumerator object to return the first element. Если MoveNext указывает, что отсутствует следующий элемент, то есть, если коллекция пуста, For Each цикл останавливается и управление передается оператору, следующему 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. В противном случае Visual Basic задает element первого элемента и выполняется блок операторов.Otherwise, Visual Basic sets element to the first element and runs the statement block.

При каждом запуске Visual Basic встречает Next оператор, он возвращает For Each инструкции.Each time Visual Basic encounters the Next statement, it returns to the For Each statement. Еще раз он вызывает MoveNext и Current для возврата следующего элемента и еще раз выполняет блок либо останавливающее цикл в зависимости от результата.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. Этот процесс продолжается до MoveNext указывает, что отсутствует следующий элемент или Exit For встречается.This process continues until MoveNext indicates that there is no next element or an Exit For statement is encountered.

Изменение коллекции.Modifying the Collection. Объект перечислителя, возвращенный GetEnumerator обычно не позволяет изменять коллекцию, добавление, удаление, замена или изменяя порядок элементов.The enumerator object returned by GetEnumerator normally doesn't let you change the collection by adding, deleting, replacing, or reordering any elements. При изменении параметров сбора после запуска For Each... Next цикл, он становится недействительным, а также приводит к следующей попытке обращения к элементу 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.

Тем не менее, эта блокировка изменения не определяются по Visual Basic, а также путем реализации IEnumerable интерфейс.However, this blocking of modification isn't determined by Visual Basic, but rather by the implementation of the IEnumerable interface. Это можно реализовать IEnumerable способом, который позволяет изменять во время итерации.It is possible to implement IEnumerable in a way that allows for modification during iteration. Если вы собираетесь производить такие динамические изменения, убедитесь, что вы понимаете характеристики IEnumerable реализации на коллекцию, вы используете.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.

Изменение элементов коллекции.Modifying Collection Elements. Current Свойство объекта перечислителя ReadOnly, и возвращает локальную копию каждого элемента коллекции.The Current property of the enumerator object is ReadOnly, and it returns a local copy of each collection element. Это означает, что нельзя изменить непосредственно к элементам в For Each... Next цикла.This means that you cannot modify the elements themselves in a For Each...Next loop. Любые изменения, внесенные влияет только на локальную копию из Current и не отражается в базовой коллекции.Any modification you make affects only the local copy from Current and isn't reflected back into the underlying collection. Тем не менее если элемент является ссылочным типом, можно изменить члены экземпляра, на который он указывает.However, if an element is a reference type, you can modify the members of the instance to which it points. В следующем примере изменяется BackColor члены каждой thisControl элемент.The following example modifies the BackColor member of each thisControl element. Нельзя Однако изменять thisControl сам.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  

Предыдущий пример можно изменить BackColor члены каждой thisControl элемент, несмотря на то, что он не может изменить thisControl сам.The previous example can modify the BackColor member of each thisControl element, although it cannot modify thisControl itself.

Обход массива.Traversing Arrays. Так как Array класс реализует IEnumerable интерфейс, предоставлять все массивы GetEnumerator метод.Because the Array class implements the IEnumerable interface, all arrays expose the GetEnumerator method. Это означает, что можно выполнить итерацию массива с For Each... Next цикла.This means that you can iterate through an array with a For Each...Next loop. Тем не менее доступен только для чтения элементов массива.However, you can only read the array elements. Их нельзя изменить.You cannot change them.

ПримерExample

В следующем примере перечисляются все папки в каталоге C:\ с помощью 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

ПримерExample

Приведенный ниже пример демонстрирует процедуру сортировки коллекции.The following example illustrates a procedure for sorting a collection. В примере сортируются экземпляры Car класса, которые хранятся в List<T>.The example sorts instances of a Car class that are stored in a List<T>. Класс Car реализует интерфейс IComparable<T>, который требует реализации метода CompareTo.The Car class implements the IComparable<T> interface, which requires that the CompareTo method be implemented.

Каждый вызов CompareTo метод выполняет одно сравнение, используемое для сортировки.Each call to the CompareTo method makes a single comparison that's used for sorting. Написанный пользователем код в методе CompareTo возвращает значение для каждого сравнения текущего объекта с другим объектом.User-written code in the CompareTo method returns a value for each comparison of the current object with another object. Возвращаемое значение меньше нуля, если текущий объект меньше другого объекта, больше нуля, если текущий объект больше другого объекта, и равняется нулю, если объекты равны.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. Это позволяет определить в коде условия для отношения «больше», «меньше» и «равно».This enables you to define in code the criteria for greater than, less than, and equal.

В методе ListCars оператор cars.Sort() сортирует список.In the ListCars method, the cars.Sort() statement sorts the list. Этот вызов метода Sort List<T> приводит к тому, что метод CompareTo вызывается автоматически для объектов Car в 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

См. такжеSee also