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. コレクション型または Object である型を持つ変数。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 & " ")
Next
Debug.WriteLine("")
'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...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 と Continue ForExit 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 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

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.

IteratorsIterators

反復子は、コレクションに対するカスタムの反復処理を実行するために使用します。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 回に 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…Next ループ内に Yield ステートメントがあります。The iterator function has a Yield statement that's inside a For…Next loop. ListEvenNumbers メソッドでは、For Each ステートメント本文の各反復で iterator 関数が呼び出され、これが次の 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 ステートメント」、および「Iterator」を参照してください。For more information, see Iterators, Yield Statement, and Iterator.

技術的な実装Technical Implementation

For EachNextWhen 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 がオン (既定の設定) の場合、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.

必要であれば、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. ほとんどの場合、これは、groupSystem.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 & " ")
        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. もう一度 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. 次の例では、各 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.

Example

次の例では、DirectoryInfo クラスを使用して、C:\ ディレクトリにあるすべてのフォルダーを一覧表示します。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. この例は、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 メソッドに対する各呼び出しは、並べ替えに使用される単一の比較を実行します。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.
    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