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 @No__t-1がオン (既定値) または @no__t が既に宣言されている場合は省略可能です。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 各項目に対して実行される、との間の1つ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.


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 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... @no__t を終了します。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

ループ内には、任意Exit Forの数のステートメントを含めることができます。 For EachYou 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.

  • @No__t-0... 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 関数が、Yield内にあるステートメント、For…Nextループします。The iterator function has a Yield statement that's inside a For…Next loop. メソッドでは、 For Eachステートメント本体の各反復処理によって、次Yieldのステートメントに進む反復子関数の呼び出しが作成されます。 ListEvenNumbersIn 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

@No__t-0... NextWhen a For EachNext ステートメントを実行すると、ループが開始される前に、Visual Basic によってコレクションが1回だけ評価されます。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連続して割り当てられている場合、ループは停止し、 Nextステートメントに続くステートメントに制御がFor Each移ります。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.

オプションの推論が 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.

必要に応じて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... など) を使用して、より信頼性の高い結果を得ることができます。またはDo... Next``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. [@No__t-0] ステートメントは、拡大変換と縮小変換の両方を許可するかどうかを制御します (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インターフェイスまた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コレクションの列挙子オブジェクトを返すメソッドを定義します。GetEnumeratorSystem.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 StrictOn設定されている場合、縮小変換は通常、コンパイラエラーになります。When Option Strict is set to On, narrowing conversions ordinarily cause compiler errors. ただし、 group elementステートメントでは、の要素からへの変換が実行時に評価されて実行され、縮小変換によって発生するコンパイラエラーは抑制されます。 For EachIn 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 Option Strict n onにLongした場合、の初期値としての割り当てはコンパイルされません。これは、からへの変換が縮小変換であるためです。IntegerIn 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. ただし、 number Long Integerステートメントでは、への代入でからへの変換が必要な場合でも、コンパイラエラーは報告されません。 For EachIn the For Each statement, however, no compiler error is reported, even though the assignment to number requires the same conversion from Long to Integer. 多数の数値が含まれているToInteger ステートメントでは、が大きい数値に適用されると、実行時エラーが発生します。For EachIn 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時に...ループが開始され、 groupが有効なコレクションオブジェクトを参照していることを Visual Basic 確認します。 NextWhen 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. は、次の要素がないことをFor Each Next 示します。つまり、コレクションが空の場合、ループは停止し、ステートメントに続くステートメントに制御MoveNextが移ります。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. それ以外の場合element 、Visual Basic は最初の要素に設定され、ステートメントブロックが実行されます。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開始した後にコレクションを変更した場合loop を使用すると、列挙子オブジェクトが無効になり、次に要素にInvalidOperationExceptionアクセスしようとすると例外が発生します。 NextIf 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. 列挙子オブジェクトのプロパティは ReadOnly であり、各コレクション要素のローカルコピーを返しCurrentます。The Current property of the enumerator object is ReadOnly, and it returns a local copy of each collection element. つまり、 For Each次のようにして、要素自体を変更することはできません。Next loop。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(thisForm As System.Windows.Forms.Form)
    For Each thisControl In thisForm.Controls
        thisControl.BackColor = System.Drawing.Color.LightBlue
    Next thisControl
End Sub

前の例では、 BackColorthisControl要素のメンバーを変更することは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 loop。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メソッドを呼び出すたびに、並べ替えに使用される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