共用方式為


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

更新: 2008 年 7 月

針對集合中的每個元素,重複一組陳述式。

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

參數

  • element
    在 For Each 陳述式中為必要項。在 Next 陳述式中是選擇項。變數。用於逐一查看集合的項目。

  • datatype
    如果尚未宣告 element,則為必要項。element 的資料型別。

  • group
    必要項。物件變數。請參考要重複 statements 的集合。

  • statements
    選擇項。在 For Each 和 Next 中,有一個或多個陳述式在 group 的每個項目上執行。

  • Exit For
    選擇項。從 For Each 迴圈當中傳出控制權。

  • Next
    必要項。結束 For Each 迴圈的定義。

備註

當您要重複執行集合或陣列之每個項目的一組陳述式時,請使用 For Each...Next 迴圈 (Loop)。

當您可以使迴圈的每個反覆運算與控制項變數產生關聯,並判斷變數的初始值和最終值時,For...Next 陳述式 (Visual Basic) 就能順利工作。不過,若您正在處理集合,則初始值和最終值的概念就沒有意義,而且不需要知道集合會具有多少個項目。在上述情形中,For Each...Next 迴圈是較好的選擇。

規則

  • 資料型別:element 的資料型別必須是可將 group 的項目轉換成它的資料型別。

    group 的資料型別必須是參考集合或陣列的參考型別。這表示 group 必須參考物件,這個物件會實作 System.Collections 命名空間的 IEnumerable 介面,或 System.Collections.Generic 命名空間的 IEnumerable<T> 介面。IEnumerable 會定義 GetEnumerator 方法,這個方法會傳回集合的列舉值物件。列舉值物件會實作 System.Collections 命名空間的 IEnumerator 介面,並公開 (Expose) Current 屬性和 ResetMoveNext 方法。Visual Basic 使用這些屬性和方法來周遊集合。

    group 的項目通常是 Object 型別,不過可以具有任何執行階段資料型別。

  • 縮小轉換:當 Option Strict 設定為 On,縮小轉換通常會造成編譯器錯誤。在下列範例中,因為將 Long 轉換為 Integer 是縮小轉換,將 m 指派為 n 初始值的作業在編譯時,Option Strict 不會是 On。

    Dim m As Long = 987
    ' Does not compile.
    'Dim n As Integer = m
    

    然而,將 group 中的項目轉換為 element 時,會在執行階段評估與執行,並隱藏縮小轉換錯誤。在下列範例中,雖然需要進行在前一個範例中造成錯誤的同一項由 Long 轉換為 Integer 的作業,但在 For Each 迴圈中不會回報編譯器錯誤。

    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. The output is 45 3 987.
            For Each p As Integer In New Long() {45, 3, 987}
                Console.Write(p & " ")
            Next
            Console.WriteLine()
        End Sub
    End Module
    
    

    不過沒有編譯器錯誤並不表示會排除執行階段錯誤的風險。在下列範例中沒有回報任何編譯器錯誤,但在將 ToInteger 套用至 9876543210 時會發生執行階段錯誤。不論 Option Strict 是 On 或是 Off 都會發生這個執行階段錯誤。

    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 = 9876543210
            'Dim n As Integer = m
    
            Try
                ' The For Each loop requires the same conversion, but
                ' is not flagged by the compiler. A run-time error is 
                ' raised because 9876543210 is too large for type Integer.
                For Each p As Integer In New Long() {45, 3, 9876543210}
                    Console.Write(p & " ")
                Next
                Console.WriteLine()
            Catch e As System.OverflowException
                Console.WriteLine()
                Console.WriteLine(e.Message)
            End Try
        End Sub
    End Module
    
    
  • 宣告:如果尚未在這個迴圈外宣告 element,就必須在 For Each 陳述式中宣告它。您可以使用 As 陳述式明確宣告 element 的型別,或者依據型別推斷指派型別。不論哪個情況,element 的範圍即是迴圈的主體。但不能在迴圈內外宣告 element。

  • 反覆運算的次數:Visual Basic 在迴圈開始之前,只會評估集合一次。如果陳述式區塊變更 element 或 group,這些變更不會影響迴圈的反覆運算。

  • 巢狀迴圈 您可以將一個迴圈置於另一個迴圈內,以便巢狀化 For Each 迴圈。不過,每個迴圈必須具備唯一的 element 變數。

    您可以將不同類型的控制結構以巢狀結構互置。如需詳細資訊,請參閱巢狀控制結構

    注意事項:

    如果先發現外部巢狀層次的 Next 陳述式才發現內部層次的 Next,編譯器會發出錯誤的信號。但是,只有當您在每個 Next 陳述式中指定 element 時,編譯器才會偵測到這個重疊錯誤。

  • 識別控制項變數:您可以在 Next 陳述式中選擇性地指定 element。這能提高程式的可讀性,尤其是在您具有巢狀 For Each 迴圈時。所指定的變數必須和相對應之 For Each 陳述式中出現的變數相同。

  • 從迴圈當中傳出Exit 陳述式 (Visual Basic):會立即將控制權傳輸至接在 Next 陳述式之後的陳述式。如果偵測到一個條件 (例如錯誤值或終止要求),而該條件會使迴圈不需要或不可能繼續重複執行,則您可能會想要結束迴圈。此外,如果在 Try...Catch...Finally 陳述式中攔截到例外狀況,則可以在 Finally 區塊的結尾使用 Exit For。

    您可以將任意數目的 Exit For 陳述式放置在 For Each 迴圈的任一處。通常會在評估某個條件之後使用 Exit For,例如在 If...Then...Else 結構中。

  • 無止盡迴圈:Exit For 的一個用處是,可以測試會造成「無止盡迴圈」(Endless Loop) 的條件,無止盡的迴圈就是會執行極多次或甚至無限次數的迴圈。如果您偵測到這類狀況,可以使用 Exit For 逸出此迴圈。如需詳細資訊,請參閱 Do...Loop 陳述式 (Visual Basic)

行為

  • 進入迴圈:開始執行 For Each...Next 迴圈時,Visual Basic 會驗證 group 是否參考有效的集合物件。如果沒有,會擲回例外狀況。否則,會呼叫 MoveNext 方法和列舉值物件的 Current 屬性,傳回第一個項目。如果 MoveNext 指出沒有下一個項目,也就是說,集合是空的,則 For Each 迴圈會終止,且控制項會傳遞至 Next 陳述式之後的陳述式。否則,Visual Basic 會將 element 設為第一個項目,並執行陳述式區塊。

  • 迴圈的反覆運算:Visual Basic 每次遇到 Next 陳述式時,就會回到 For Each 陳述式。接著再次呼叫 MoveNextCurrent 傳回下一個項目,並根據結果再次執行區塊或終止迴圈。此處理序會繼續執行,直到 MoveNext 指出沒有下一個項目,或是遇到 Exit For 陳述式為止。

  • 終止迴圈:當集合中所有的項目都已連續指派給 element 時,For Each 迴圈會終止,且控制會傳遞至 Next 陳述式之後的陳述式。

  • 變更反覆運算值:在迴圈內變更 element 的值,會使程式碼更難閱讀及偵錯。變更 group 的值不會影響集合或它的項目,這是初次進入迴圈時要判斷的項目。

  • 走訪順序:當您執行 For Each...Next 迴圈時,集合的走訪順序是由 GetEnumerator 方法所傳回的列舉值物件所控制。走訪順序不是由 Visual Basic 判斷,而是由列舉值物件的 MoveNext 方法判斷。這表示您可能無法預測哪一個集合項目會在 element 中第一個傳回,或者哪一個項目會接在指定之項目後傳回。

    如果程式碼需要以特定順序走訪集合,則 For Each...Next 迴圈不是最佳選擇 (除非您了解集合公開之列舉值物件的特性)。使用不同的迴圈結構 (例如,For...Next 或 Do...Loop),可以獲得更可靠的結果。

  • 修改集合GetEnumerator 傳回的列舉值物件通常不允許您經由新增、刪除、取代或重新排列任何項目的方式改變集合。如果您在初始 For Each...Next 迴圈後改變集合,列舉值物件會變成無效,而且在下次嘗試存取項目時會發生 InvalidOperationException 例外狀況。

    但是,不允許修改並不是由 Visual Basic 決定,而是由 IEnumerable 介面的實作 (Implementation) 方式決定。您也可以實作 IEnumerable,允許在反覆運算時進行修改。如果您考慮要進行這類動態修改,對於您所使用的集合,請務必了解 IEnumerable 實作的特性。

  • 修改集合項目:列舉值物件的 Current 屬性是 ReadOnly (Visual Basic),而且它會傳回每一個集合項目的本機複本。這表示您無法在 For Each...Next 迴圈中修改項目本身。您所做的任何修改只會影響 Current 的本機複本,而不會反映回基礎集合中。然而,如果項目是參考型別,您可以修改它所指向的執行個體成員。下列範例將說明這點。

    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
    

    上述範例可以修改每個 thisControl 項目的 BackColor 成員,不過它無法修改 thisControl 本身。

  • 走訪陣列:因為 Array 類別會實作 IEnumerable 介面,因此全部的陣列都會公開 GetEnumerator 方法。這表示您可以使用 For Each...Next 逐一查看陣列。不過,您只能夠讀取陣列的項目,而無法改變它。如需說明,請參閱 HOW TO:在集合或陣列中執行各元素的多個陳述式

範例

下列範例會使用 For Each...Next 陳述式,在集合的所有項目中搜尋字串 "Hello"。此範例會假設已建立 thisCollection 集合,且這個集合的項目型別為 String。

Dim found As Boolean = False
Dim thisCollection As New Collection
For Each thisObject As String In thisCollection
    If thisObject = "Hello" Then
        found = True
        Exit For
    End If
Next thisObject

請參閱

工作

HOW TO:在集合或陣列中執行各元素的多個陳述式

HOW TO:改善迴圈的效能

概念

迴圈結構

Visual Basic 中的集合

擴展和縮小轉換

參考

While...End While 陳述式 (Visual Basic)

Do...Loop 陳述式 (Visual Basic)

變更記錄

日期

記錄

原因

2008 年 7 月

加入關於縮小轉換的章節。

客戶回函。