반복 문 - for
, foreach
, do
, while
반복 문은 명령문 또는 명령문 블록을 반복적으로 실행합니다. for
문: 지정된 부울 식이 true
로 계산되는 동안 본문을 실행합니다. foreach
문: 컬렉션의 요소를 열거하고 컬렉션의 각 요소에 대한 본문을 실행합니다. do
문: 조건에 따라 본문을 한 번 이상 실행합니다. while
문: 조건에 따라 본문을 0번 이상 실행합니다.
반복 문 내의 어느 지점에서나 break
문을 사용하여 루프를 중단할 수 있습니다. continue
문을 사용하여 루프에서 다음 반복으로 이동할 수 있습니다.
for
문
for
문은 지정된 부울 식이 true
로 계산되는 동안 문 또는 문 블록을 실행합니다. 다음 예제에서는 정수 카운터가 3보다 작으므로 본문을 실행하는 for
문을 보여 줍니다.
for (int i = 0; i < 3; i++)
{
Console.Write(i);
}
// Output:
// 012
위의 예제에서는 for
문의 요소를 보여 줍니다.
루프로 유입되기 전에 한 번만 실행되는 initializer 섹션입니다. 일반적으로 해당 섹션에서 로컬 루프 변수를 선언하고 초기화합니다. 선언된 변수는
for
문 외부에서 액세스할 수 없습니다.앞의 예제에서 이니셜라이저 섹션은 정수 카운터 변수를 선언하고 초기화합니다.
int i = 0
루프의 다음 반복을 실행할지 여부를 결정하는 condition 섹션입니다. 이 결과가
true
이거나 없으면 다음 반복이 실행되고, 그렇지 않으면 루프가 종료됩니다. condition 섹션은 부울 식이어야 합니다.앞의 예제에서 condition 섹션은 카운터 값이 3보다 적은지 확인합니다.
i < 3
루프의 본문을 실행할 때마다 수행되는 작업을 정의하는 iterator 섹션입니다.
앞의 예제에서 iterator 섹션은 카운터를 증가시킵니다.
i++
루프의 본문은 명령문 또는 명령문의 블록입니다.
iterator 섹션에는 쉼표로 구분된 다음 명령문 식이 0개 이상 포함될 수 있습니다.
- 접두사 또는 후위 increment 식(예:
++i
또는i++
) - 접두사 또는 후위 decrement 식(예:
--i
또는i--
) - 할당
- 메서드 호출
await
식new
연산자를 사용하여 개체 만들기
initializer 섹션에서 루프 변수를 선언하지 않는 경우 initializer 섹션의 이전 목록에서 0개 이상의 식을 사용할 수 있습니다. 다음 예제에서는 initializer 섹션에서 외부 변수에 값 할당, initializer 및 iterator 섹션에서 메서드 호출, iterator 섹션에서 두 변수의 값 변경과 같이 initializer 및 iterator 섹션의 여러 가지 덜 일반적인 사용법을 보여 줍니다.
int i;
int j = 3;
for (i = 0, Console.WriteLine($"Start: i={i}, j={j}"); i < j; i++, j--, Console.WriteLine($"Step: i={i}, j={j}"))
{
//...
}
// Output:
// Start: i=0, j=3
// Step: i=1, j=2
// Step: i=2, j=1
for
문의 모든 섹션은 선택 사항입니다. 예를 들어 다음 코드는 무한 for
루프를 정의합니다.
for ( ; ; )
{
//...
}
foreach
문
foreach
문은 다음 예제와 같이 System.Collections.IEnumerable 또는 System.Collections.Generic.IEnumerable<T> 인터페이스를 구현하는 형식의 인스턴스에 있는 각 요소에 대해 문 또는 문 블록을 실행합니다.
List<int> fibNumbers = new() { 0, 1, 1, 2, 3, 5, 8, 13 };
foreach (int element in fibNumbers)
{
Console.Write($"{element} ");
}
// Output:
// 0 1 1 2 3 5 8 13
foreach
문은 이러한 형식으로 제한되지 않습니다. 다음 조건을 충족하는 모든 형식의 인스턴스와 함께 사용할 수 있습니다.
- 형식에 public 매개 변수가 없는
GetEnumerator
메서드가 있습니다.GetEnumerator
메서드는 형식의 확장 메서드일 수 있습니다. GetEnumerator
메서드의 반환 형식이 publicCurrent
속성과 반환 형식이bool
인 public 매개 변수가 없는MoveNext
메서드를 포함합니다.
다음 예제에서는 인터페이스를 구현하지 않는 System.Span<T> 형식의 인스턴스와 함께 foreach
문을 사용합니다.
Span<int> numbers = [3, 14, 15, 92, 6];
foreach (int number in numbers)
{
Console.Write($"{number} ");
}
// Output:
// 3 14 15 92 6
열거자의 Current
속성이 참조 반환 값(ref T
여기서 T
는 컬렉션 요소의 형식임)을 반환하는 경우 다음 예제와 같이 ref
또는 ref readonly
한정자를 사용하여 반복 변수를 선언할 수 있습니다.
Span<int> storage = stackalloc int[10];
int num = 0;
foreach (ref int item in storage)
{
item = num++;
}
foreach (ref readonly var item in storage)
{
Console.Write($"{item} ");
}
// Output:
// 0 1 2 3 4 5 6 7 8 9
foreach
문의 소스 컬렉션이 비어 있으면 foreach
문의 본문이 실행되지 않고 건너뜁니다. foreach
문이 null
에 적용되면 NullReferenceException이 throw됩니다.
await foreach
await foreach
문을 사용하여 비동기 데이터 스트림 즉, IAsyncEnumerable<T> 인터페이스를 구현하는 컬렉션 형식을 사용할 수 있습니다. 루프의 각 반복은 다음 요소가 비동기적으로 검색되는 동안 일시 중단될 수도 있습니다. 다음 예제에서는 await foreach
문을 사용하는 방법을 보여줍니다.
await foreach (var item in GenerateSequenceAsync())
{
Console.WriteLine(item);
}
다음 조건을 충족하는 모든 형식의 인스턴스와 함께 await foreach
문을 사용할 수도 있습니다.
- 형식에 public 매개 변수가 없는
GetAsyncEnumerator
메서드가 있습니다. 해당 메서드는 형식의 확장 메서드일 수 있습니다. GetAsyncEnumerator
메서드의 반환 형식에는 publicCurrent
속성과 반환 형식이Task<bool>
,ValueTask<bool>
또는 awaiter의GetResult
메서드가bool
값을 반환하는 다른 모든 대기 가능 형식이 포함된 public 매개 변수가 없는MoveNextAsync
메서드가 있습니다.
기본적으로 스트림 요소는 캡처된 컨텍스트에서 처리됩니다. 컨텍스트 캡처를 사용하지 않도록 설정하려면 TaskAsyncEnumerableExtensions.ConfigureAwait 확장 메서드를 사용합니다. 동기화 컨텍스트 및 현재 컨텍스트 캡처에 대한 자세한 내용은 작업 기반 비동기 패턴 사용을 참조하세요. 비동기 스트림에 대한 자세한 내용은 비동기 스트림 자습서를 참조하세요.
반복 변수의 형식
다음 코드와 같이 var
키워드를 사용하여 컴파일러가 foreach
문에서 반복 변수의 형식을 유추할 수 있습니다.
foreach (var item in collection) { }
참고 항목
var
형식은 null 허용 인식 컨텍스트가 사용하도록 설정되었는지 여부와 초기화 식의 형식이 참조 형식인지 여부에 따라 컴파일러에서 null 허용 참조 형식으로 유추될 수 있습니다.
자세한 내용은 암시적으로 형식화된 지역 변수를 참조하세요.
다음 코드와 같이 반복 변수의 형식을 명시적으로 지정할 수도 있습니다.
IEnumerable<T> collection = new T[5];
foreach (V item in collection) { }
위의 양식에서 컬렉션 요소의 T
형식은 암시적 또는 명시적으로 반복 변수의 V
형식으로 변환할 수 있어야 합니다. T
에서 V
로의 명시적 변환이 런타임에 실패하는 경우 foreach
문은 InvalidCastException을 throw합니다. 예를 들어 T
가 봉인되지 않은 클래스 형식인 경우 V
는 T
가 구현하지 않는 형식을 포함하여 모든 인터페이스 형식일 수 있습니다. 런타임에 컬렉션 요소의 형식은 T
에서 파생되어 실제로 V
를 구현하는 형식일 수 있습니다. 그렇지 않은 경우에는 InvalidCastException을 throw합니다.
do
문
do
문은 지정된 부울 식이 true
로 계산되는 동안 문 또는 문 블록을 실행합니다. 이 식은 각 루프 실행 후 평가되기 때문에 do
루프가 한 번 이상 실행됩니다. do
루프는 0회 이상 실행되는 while
루프와 다릅니다.
다음 예제에서는 do
문의 사용량을 보여 줍니다.
int n = 0;
do
{
Console.Write(n);
n++;
} while (n < 5);
// Output:
// 01234
while
문
while
문은 지정된 부울 식이 true
로 계산되는 동안 문 또는 문 블록을 실행합니다. 이 식은 각 루프를 실행하기 전에 평가되기 때문에 while
루프는 0번 이상 실행됩니다. while
루프는 한 번 이상 실행되는 do
루프와 다릅니다.
다음 예제에서는 while
문의 사용량을 보여 줍니다.
int n = 0;
while (n < 5)
{
Console.Write(n);
n++;
}
// Output:
// 01234
C# 언어 사양
자세한 내용은 C# 언어 사양의 다음 섹션을 참조하세요.
이러한 기능에 대한 자세한 내용은 다음 기능 제안 노트를 참조하세요.
참고 항목
.NET