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 DefinitionDefinition
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が on (既定値) または 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. group内の各項目に対して実行される For EachNext 間の1つ以上のステートメント。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.


For...Next ステートメントは、ループの各反復処理を制御変数に関連付けて、その変数の初期値と最終値を決定できる場合に適しています。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 LoopsNested Loops

ループを入れ子にするには、別のループ内にループを挿入し For Each ます。You can nest For Each loops by putting one loop within another.

次の例では、入れ子になった For Each...Next を示します。The 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 と Continue ForExit For and Continue For

Exit Forステートメントを実行すると、For...Next が終了しますThe 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
' Output: 1 2 3 4 9 10

For Each ループには、任意の数の Exit For ステートメントを含めることができます。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でキャッチされます。Finally ブロックの末尾に Exit For を使用することもできます。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. 詳細については、「Do...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 ステートメントを使用して、コレクションの各要素を一度に1つ返します。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.

次の例では、iterator 関数を使用します。The following example uses an iterator function. Iterator 関数には、For... の内部にある 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 & " ")
    ' 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 によってコレクションが1回だけ評価されます。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 ステートメントが on (既定の設定) の場合、Visual Basic コンパイラは elementのデータ型を推測できます。If 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.

必要に応じて、Next ステートメントで element を指定することもできます。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. ただし、コンパイラは、すべての Next ステートメントで element を指定した場合にのみ、この重複エラーを検出できます。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.

ランタイムは、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 は、System.Collections 名前空間の IEnumerable インターフェイスまたは System.Collections.Generic 名前空間の IEnumerable<T> インターフェイスを実装するオブジェクトを参照します。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 名前空間の System.Collections.IEnumerator インターフェイスを実装し、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 StrictOnに設定されている場合、通常、縮小変換ではコンパイラエラーが発生します。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.

次の例では、n の初期値としての m の割り当ては 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 & " ")
        ' 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 ループの実行が開始されると、group が有効なコレクションオブジェクトを参照していることが Visual Basic 検証されます。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. このプロセスは、次の要素が存在しないこと、または Exit For ステートメントが発生したことが MoveNext によって示されるまで続行されます。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. 次の例では、各 thisControl 要素の BackColor メンバーを変更します。The following example modifies the BackColor member of each thisControl element. ただし、thisControl 自体を変更することはできません。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

前の例では、各 thisControl 要素の BackColor メンバーを変更できますが、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. この例では、List<T>に格納されている Car クラスのインスタンスを並べ替えます。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 メソッドを呼び出すたびに、並べ替えに使用される1つの比較が行われます。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. SortList<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.

    ' 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