For Each...Next 陳述式 (Visual Basic)For Each...Next Statement (Visual Basic)

每個項目集合中,會重複一組陳述式。Repeats a group of statements for each element in a collection.


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


詞彙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 EachNext中的每個項目上執行groupOne 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...下一個陳述式運作良好時,您便可以控制變數相關聯的迴圈的每個反覆項目上,並判斷該變數的初始和最終值。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 & " ")
'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 & " ")
'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

Exit 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 ForExit 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
' 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.


您使用迭代器若要在集合上執行自訂反覆項目。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內的陳述式For...下一步迴圈。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 & " ")
    ' 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
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. 如果陳述式區塊變更elementgroup,這些變更不會影響在迴圈的反覆項目。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 編譯器可以推斷的資料型別elementIf Option Infer is on (its default setting), the Visual Basic compiler can infer the data type of element. 如果是 off 和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.

您可以選擇性地指定elementNext陳述式。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...NextDo...Loop.You might achieve more reliable results using a different loop structure, such as For...Next or Do...Loop.

執行階段必須能夠轉換中的項目groupelementThe 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屬性並ResetMoveNext方法。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陳述式,不過中的項目從不groupelement評估和執行在執行階段,而造成的縮小轉換的編譯器錯誤受到抑制。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是上,因為轉換LongInteger是縮小轉換。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需要從相同的轉換LongIntegerIn 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 & " ")
        ' 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 & " ")

    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. 它會呼叫一次MoveNextCurrent傳回下一個項目,再執行此區塊或根據結果迴圈就會停止。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.


下列範例會列出在 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()


下列範例說明排序集合的程序。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. List<T>Sort 方法的這個呼叫,會導致 CompareTo 方法對 ListCar 物件自動呼叫。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.

    ' View all of the cars.
    For Each thisCar As Car In cars
        Debug.Write(thisCar.Color.PadRight(5) & " ")
        Debug.Write(thisCar.Speed.ToString & " ")

    ' 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