컬렉션의 각 요소에 대해 문 그룹을 반복합니다.
문법
For Each element [ As datatype ] In group
[ statements ]
[ Continue For ]
[ statements ]
[ Exit For ]
[ statements ]
Next [ element ]
부분
| 기간 | 정의 |
|---|---|
element |
문장에 For Each 반드시 필요합니다. 문의 선택 사항입니다 Next . 변수 컬렉션의 요소를 반복하는 데 사용됩니다. |
datatype |
선택 사항인 경우Option Infer(기본값) 또는 element 이미 선언되어 있습니다. 꺼져 있고 element 아직 선언되지 않은 경우 Option Infer 필요합니다. 의 데이터 형식입니다 element. |
group |
필수 사항입니다. 컬렉션 형식 또는 개체 형식의 변수입니다. 반복할 컬렉션을 statements 참조합니다. |
statements |
선택 사항입니다. 의 각 항목group에서 실행되는 문 사이에 NextFor Each 하나 이상의 문이 있습니다. |
Continue For |
선택 사항입니다. 루프의 시작 부분에 컨트롤을 전송합니다 For Each . |
Exit For |
선택 사항입니다.
For Each 루프에서 제어를 벗어납니다. |
Next |
필수 사항입니다. 루프의 정의를 종료합니다 For Each . |
간단한 예제
For Each컬렉션 또는 배열의 각 요소에 대해 문 집합을 반복하려는 경우 ...Next 루프를 사용합니다.
팁 (조언)
A For... 다음 문은 루프의 각 반복을 컨트롤 변수와 연결하고 해당 변수의 초기 및 최종 값을 결정할 수 있는 경우에 적합합니다. 그러나 컬렉션을 처리할 때 초기 값과 최종 값의 개념은 의미가 없으며 컬렉션에 포함된 요소의 수를 반드시 알 수는 없습니다. 이런 종류의 경우 For Each...Next 루프가 종종 더 나은 선택입니다.
다음 예제 For Each에서는 ...
Next 문은 List 컬렉션의 모든 요소를 반복합니다.
' 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 Each
다음 예제에서는 중첩된 For Each...
Next 구조체입니다.
' 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 변수가 있어야 합니다.
서로 다른 종류의 컨트롤 구조를 중첩할 수도 있습니다. 자세한 내용은 중첩된 컨트롤 구조를 참조하세요.
For 루프 종료 및 계속 실행
Exit For 문으로 인해 실행이 ...를 종료합니다For.
Next 루프를 종료하고 제어를 Next 문 다음의 문으로 전송합니다.
다음 반복으로 즉시 제어를 넘기는 Continue For 문입니다. 자세한 내용은 Continue 문을 참조하세요.
다음 예제에서는 및 Exit For 문을 사용하는 Continue For 방법을 보여 줍니다.
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 8, 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
여러 Exit For 문을 루프에 For Each 넣을 수 있습니다. 중첩된 For Each 루프 Exit For 내에서 사용하면 실행이 가장 안쪽 루프를 종료하고 다음 상위 수준의 중첩으로 제어를 전송합니다.
Exit For는 몇 가지 조건(예: ...Then)을 평가한 If후에 자주 사용됩니다....Else 구조. 다음 조건에 사용할 Exit For 수 있습니다.
반복을 계속하는 것은 불필요하거나 불가능합니다. 잘못된 값 또는 종료 요청으로 인해 발생할 수 있습니다.
예외는
Try...Catch...Finally. 블록의Finally끝에서 사용할Exit For수 있습니다.무한 루프가 있습니다. 이 루프는 횟수가 크거나 무한할 수 있습니다. 이러한 조건을 감지하는 경우 루프를 이스케이프하는 데 사용할
Exit For수 있습니다. 자세한 내용은 Do...Loop 문을 참조하세요.
이터레이터
반복기를 사용하여 컬렉션에 대한 사용자 지정 반복을 수행합니다. 반복기는 함수 또는 접근자 Get 일 수 있습니다. 문을 Yield 사용하여 컬렉션의 각 요소를 한 번에 하나씩 반환합니다.
문을 사용하여 반복기를 호출합니다 For Each...Next . 각각의 For Each 루프의 반복이 반복기를 호출합니다.
Yield 반복기에서 문에 도달하면 문의 식 Yield 이 반환되고 코드의 현재 위치가 유지됩니다. 다음에 반복기가 호출되면 해당 위치에서 실행이 다시 시작됩니다.
다음 예제에서는 반복기 함수를 사용합니다. 반복기 함수에는 YieldFor... 다음 루프. 메서드에서 ListEvenNumbers 문 본문의 For Each 각 반복은 다음 Yield 문으로 진행되는 반복기 함수에 대한 호출을 만듭니다.
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 문 및 반복기를 참조하세요.
기술 구현
때 ...For Each
Next 문이 실행되면 Visual Basic은 루프가 시작되기 전에 컬렉션을 한 번만 평가합니다. 명령문이 변경되거나 group이러한 element 변경 내용이 루프 반복에 영향을 주지 않습니다.
컬렉션의 모든 요소가 연속적으로 할당 element되면 루프가 For Each 중지되고 제어가 문 다음 Next 문으로 전달됩니다.
Option Infer가 켜진 경우(기본 설정) Visual Basic 컴파일러는 데이터 형식element을 유추할 수 있습니다. 꺼져 있고 element 루프 외부에서 선언되지 않은 경우 문에서 For Each 선언해야 합니다. 명시적으로 데이터 형식 element 을 선언하려면 절을 As 사용합니다. 요소의 데이터 형식이 ...Next 구문 외부에서 For Each정의되지 않는 한 해당 범위는 루프의 본문입니다. 루프 외부와 내부 둘 다 선언 element 할 수 없습니다.
필요에 따라 문에서 Next 지정할 element 수 있습니다. 이렇게 하면 특히 중첩된 For Each 루프가 있는 경우 프로그램의 가독성이 향상됩니다. 해당 For Each 문에 나타나는 변수와 동일한 변수를 지정해야 합니다.
루프 내부의 값을 element 변경하지 않도록 할 수 있습니다. 이렇게 하면 코드를 읽고 디버그하기가 더 어려워질 수 있습니다. 값을 group 변경해도 루프가 처음 입력되었을 때 결정된 컬렉션이나 해당 요소에는 영향을 주지 않습니다.
루프를 중첩하는 경우 Next 내부 수준 앞에 Next 외부 중첩 수준의 문이 발생하면 컴파일러에서 오류를 알릴 수 있습니다. 그러나 컴파일러는 element를 모든 Next 문에서 명시하는 경우에만 이 겹치는 오류를 검색할 수 있습니다.
코드가 특정 순서 For Each로 컬렉션을 트래버스하는 데 의존하는 경우 컬렉션이 노출하는 열거자 개체의 특징을 알지 못하면 ...Next 루프가 최선의 선택이 아닙니다. 순회 순서는 Visual Basic이 아니라 열거자 개체의 메서드에 의해 MoveNext 결정됩니다. 따라서 컬렉션의 어떤 요소가 가장 먼저 반환될지 또는 지정된 요소 다음에 반환 element될 다음 요소를 예측할 수 없을 수도 있습니다. ... 또는 Do...NextLoop와 같은 For다른 루프 구조를 사용하여 보다 안정적인 결과를 얻을 수 있습니다.
런타임에서 요소를 groupelement.로 변환할 수 있어야 합니다. [Option Strict] 문은 확대 및 축소 변환이 모두 허용되는지(Option Strict 해제됨, 기본값) 또는 확대 변환만 허용되는지(Option Strict 켜기) 여부를 제어합니다. 자세한 내용은 축소 변환을 참조하세요.
데이터 형식 group 은 열거 가능한 컬렉션 또는 배열을 참조하는 참조 형식이어야 합니다. 가장 일반적으로 이는 네임스페이 group 스의 인터페이스 또는 네임스페이스의 IEnumerable 인터페이스 System.Collections 를 구현하는 개체를 IEnumerable<T>System.Collections.Generic 참조한다는 것을 의미합니다.
System.Collections.IEnumerable 는 컬렉션에 GetEnumerator 대한 열거자 개체를 반환하는 메서드를 정의합니다. 열거자 개체는 네임스페이 System.Collections.IEnumerator 스의 인터페이스를 System.Collections 구현하고 속성과 메서드를 ResetMoveNext 노출합니다Current. Visual Basic은 이러한 컬렉션을 사용하여 컬렉션을 트래버스합니다.
축소 변환
로 설정On되면 Option Strict 변환 범위를 좁히면 일반적으로 컴파일러 오류가 발생합니다.
For Each 그러나 문에서 요소 groupelement 의 변환은 런타임에 평가 및 수행되며 축소 변환으로 인한 컴파일러 오류는 표시되지 않습니다.
다음 예제에서는 변환이 축소 변환이므로 초기 값으로 할당 m 이 켜지면 LongInteger 컴파일 Option Strict 되지 n 않습니다.
For Each 그러나 이 문에서는 할당 number 에 동일한 변환 LongInteger이 필요하더라도 컴파일러 오류가 보고되지 않습니다.
For Each 큰 숫자가 포함된 문에서 런타임 오류는 큰 숫자에 적용될 때 ToInteger 발생합니다.
Option Strict On
Imports System
Module Program
Sub Main(args As String())
' 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
End Sub
End Module
IEnumerator 호출
...Next 루프 실행이 For Each시작되면 Visual Basic은 유효한 컬렉션 개체를 참조하는지 확인 group 합니다. 그렇지 않은 경우 예외를 throw합니다. 그렇지 않으면 첫 번째 요소를 반환하기 위해 열거자 개체의 메서드와 Current 속성을 호출 MoveNext 합니다. 다음 요소가 없음을 나타내는 경우 MoveNext , 즉 컬렉션이 비어 있으면 루프가 For Each 중지되고 제어가 문 다음 Next 문으로 전달됩니다. 그렇지 않으면 Visual Basic이 첫 번째 요소로 설정하고 element 문 블록을 실행합니다.
Visual Basic이 문을 발견할 Next 때마다 문으로 For Each 돌아갑니다. 다시 호출 MoveNext 하고 Current 다음 요소를 반환하고, 결과에 따라 블록을 실행하거나 루프를 중지합니다. 이 프로세스는 다음 요소가 Exit For 없거나 문이 발견될 때까지 MoveNext 계속됩니다.
컬렉션 수정 일반적으로 반환되는 GetEnumerator 열거자 개체는 요소를 추가, 삭제, 바꾸기 또는 다시 정렬하여 컬렉션을 변경할 수 없습니다. ...Next 루프를 시작한 For Each후 컬렉션을 변경하면 열거자 개체가 유효하지 않으며 요소에 액세스하려고 하면 예외가 InvalidOperationException 발생합니다.
그러나 이러한 수정 차단은 Visual Basic에 의해 결정되지 않고 인터페이스 구현에 IEnumerable 의해 결정됩니다. 반복하는 동안 수정을 허용하는 방식으로 구현 IEnumerable 할 수 있습니다. 이러한 동적 수정을 고려하는 경우 사용 중인 컬렉션에서 구현의 IEnumerable 특성을 이해해야 합니다.
컬렉션 요소 수정
Current 열거자 개체의 속성은 ReadOnly이며 각 컬렉션 요소의 로컬 복사본을 반환합니다. 즉, ...Next 루프에서 For Each요소 자체를 수정할 수 없습니다. 수정한 내용은 로컬 복사본 Current 에만 영향을 미치며 기본 컬렉션에 다시 반영되지 않습니다. 그러나 요소가 참조 형식인 경우 요소가 가리키는 인스턴스의 멤버를 수정할 수 있습니다. 다음 예제에서는 각 thisControl 요소의 멤버를 BackColor 수정합니다. 그러나 자체 수정 thisControl 할 수는 없습니다.
Sub LightBlueBackground(thisForm As System.Windows.Forms.Form)
For Each thisControl In thisForm.Controls
thisControl.BackColor = System.Drawing.Color.LightBlue
Next thisControl
End Sub
이전 예제에서는 자체 수정할 BackColor 수는 없지만 각 thisControl 요소의 멤버를 수정 thisControl 할 수 있습니다.
배열 트래버스 클래스가 Array 인터페이스를 IEnumerable 구현하기 때문에 모든 배열은 메서드를 노출합니다 GetEnumerator . 즉, ...Next 루프를 사용하여 배열For Each을 반복할 수 있습니다. 그러나 배열 요소만 읽을 수 있습니다. 변경할 수 없습니다.
예제 1
다음 예제에서는 클래스를 사용하여 C:\ 디렉터리의 모든 폴더를 나열합니다 DirectoryInfo .
Dim dInfo As New System.IO.DirectoryInfo("c:\")
For Each dir As System.IO.DirectoryInfo In dInfo.GetDirectories()
Debug.WriteLine(dir.Name)
Next
예제 2
다음 예제에서는 컬렉션을 정렬하는 절차를 보여 줍니다. 이 예제에서는 에 저장된 클래스의 Car 인스턴스를 정렬합니다 List<T>. 클래스는 Car 메서드를 IComparable<T> 구현해야 하는 인터페이스를 CompareTo 구현합니다.
메서드에 대한 각 호출은 CompareTo 정렬에 사용되는 단일 비교를 만듭니다. 메서드의 사용자가 작성한 코드는 CompareTo 현재 개체와 다른 개체를 비교할 때마다 값을 반환합니다. 현재 개체가 다른 개체보다 작으면 반환되는 값이 0보다 작고, 현재 개체가 다른 개체보다 크면 0보다 크고, 같으면 0보다 큽니다. 이렇게 하면 코드에서 보다 큼, 보다 작음 및 같음의 조건을 정의할 수 있습니다.
메서드에서 ListCars 문은 cars.Sort() 목록을 정렬합니다. 메서드를 SortList<T> 호출하면 메서드가 CompareTo 해당 개체List에 대해 Car 자동으로 호출됩니다.
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
참고하십시오
.NET