foreach, in(C# 참조)foreach, in (C# reference)

foreach 문은 다음 예제와 같이 System.Collections.IEnumerable 또는 System.Collections.Generic.IEnumerable<T> 인터페이스를 구현하는 형식의 인스턴스에 있는 각 요소에 대해 문 또는 문 블록을 실행합니다.The foreach statement executes a statement or a block of statements for each element in an instance of the type that implements the System.Collections.IEnumerable or System.Collections.Generic.IEnumerable<T> interface, as the following example shows:

var fibNumbers = new List<int> { 0, 1, 1, 2, 3, 5, 8, 13 };
int count = 0;
foreach (int element in fibNumbers)
{
    Console.WriteLine($"Element #{count}: {element}");
    count++;
}
Console.WriteLine($"Number of elements: {count}");

foreach 문은 이러한 형식으로 제한되지 않습니다.The foreach statement isn't limited to those types. 다음 조건을 충족하는 모든 형식의 인스턴스와 함께 사용할 수 있습니다.You can use it with an instance of any type that satisfies the following conditions:

  • 형식에는 반환 형식이 클래스, 구조체 또는 인터페이스 유형인 public 매개 변수가 없는 GetEnumerator 메서드가 포함됩니다.A type has the public parameterless GetEnumerator method whose return type is either class, struct, or interface type. C# 9.0부터는 GetEnumerator 메서드가 형식의 확장 메서드일 수 있습니다.Beginning with C# 9.0, the GetEnumerator method can be a type's extension method.
  • GetEnumerator 메서드의 반환 형식이 public Current 속성과 반환 형식이 Boolean인 public 매개 변수가 없는 MoveNext 메서드를 포함합니다.The return type of the GetEnumerator method has the public Current property and the public parameterless MoveNext method whose return type is Boolean.

다음 예제에서는 인터페이스를 구현하지 않는 System.Span<T> 형식의 인스턴스와 함께 foreach 문을 사용합니다.The following example uses the foreach statement with an instance of the System.Span<T> type, which doesn't implement any interfaces:

public class IterateSpanExample
{
    public static void Main()
    {
        Span<int> numbers = new int[] { 3, 14, 15, 92, 6 };
        foreach (int number in numbers)
        {
            Console.Write($"{number} ");
        }
        Console.WriteLine();
    }
}

C# 7.3부터는 열거자의 Current 속성이 참조 반환 값(ref T 여기서 T는 컬렉션 요소의 형식임)을 반환하는 경우 다음 예제와 같이 ref 또는 ref readonly 한정자를 사용하여 반복 변수를 선언할 수 있습니다.Beginning with C# 7.3, if the enumerator's Current property returns a reference return value (ref T where T is the type of a collection element), you can declare an iteration variable with the ref or ref readonly modifier, as the following example shows:

public class ForeachRefExample
{
    public static void Main()
    {
        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
    }
}

C# 8.0부터는 await foreach 문을 사용하여 비동기 데이터 스트림 즉, IAsyncEnumerable<T> 인터페이스를 구현하는 컬렉션 형식을 사용할 수 있습니다.Beginning with C# 8.0, you can use the await foreach statement to consume an asynchronous stream of data, that is, the collection type that implements the IAsyncEnumerable<T> interface. 루프의 각 반복은 다음 요소가 비동기적으로 검색되는 동안 일시 중단될 수도 있습니다.Each iteration of the loop may be suspended while the next element is retrieved asynchronously. 다음 예제에서는 await foreach 문을 사용하는 방법을 보여줍니다.The following example shows how to use the await foreach statement:

await foreach (var item in GenerateSequenceAsync())
{
    Console.WriteLine(item);
}

기본적으로 스트림 요소는 캡처된 컨텍스트에서 처리됩니다.By default, stream elements are processed in the captured context. 컨텍스트 캡처를 사용하지 않도록 설정하려면 TaskAsyncEnumerableExtensions.ConfigureAwait 확장 메서드를 사용합니다.If you want to disable capturing of the context, use the TaskAsyncEnumerableExtensions.ConfigureAwait extension method. 동기화 컨텍스트 및 현재 컨텍스트 캡처에 대한 자세한 내용은 작업 기반 비동기 패턴 사용을 참조하세요.For more information about synchronization contexts and capturing the current context, see Consuming the Task-based asynchronous pattern. 비동기 스트림에 대한 자세한 내용은 C# 8.0의 새로운 기능 문서의 비동기 스트림 섹션을 참조하세요.For more information about asynchronous streams, see the Asynchronous streams section of the What's new in C# 8.0 article.

foreach 문 블록 내 원하는 지점에서 break 문을 사용하여 루프를 중단하거나 continue 문을 사용하여 루프의 다음 반복을 한 단계 실행할 수 있습니다.At any point within the foreach statement block, you can break out of the loop by using the break statement, or step to the next iteration in the loop by using the continue statement. goto, return 또는 throw 문으로 foreach 루프를 종료할 수도 있습니다.You can also exit a foreach loop by the goto, return, or throw statements.

foreach 문이 null에 적용되면 NullReferenceException이 throw됩니다.If the foreach statement is applied to null, a NullReferenceException is thrown. foreach 문의 소스 컬렉션이 비어 있으면 foreach 루프의 본문이 실행되지 않고 건너뜁니다.If the source collection of the foreach statement is empty, the body of the foreach loop isn't executed and skipped.

반복 변수의 형식Type of an iteration variable

다음 코드와 같이 var 키워드를 사용하여 컴파일러가 foreach 문에서 반복 변수의 형식을 유추할 수 있습니다.You can use the var keyword to let the compiler infer the type of an iteration variable in the foreach statement, as the following code shows:

foreach (var item in collection) { }

다음 코드와 같이 반복 변수의 형식을 명시적으로 지정할 수도 있습니다.You can also explicitly specify the type of an iteration variable, as the following code shows:

IEnumerable<T> collection = new T[5];
foreach (V item in collection) { }

위의 양식에서 컬렉션 요소의 T 형식은 암시적 또는 명시적으로 반복 변수의 V 형식으로 변환할 수 있어야 합니다.In the preceding form, type T of a collection element must be implicitly or explicitly convertible to type V of an iteration variable. T에서 V로의 명시적 변환이 런타임에 실패하는 경우 foreach 문은 InvalidCastException을 throw합니다.If an explicit conversion from T to V fails at run time, the foreach statement throws an InvalidCastException. 예를 들어 T가 봉인되지 않은 클래스 형식인 경우 VT가 구현하지 않는 형식을 포함하여 모든 인터페이스 형식일 수 있습니다.For example, if T is a non-sealed class type, V can be any interface type, even the one that T doesn't implement. 런타임에 컬렉션 요소의 형식은 T에서 파생되어 실제로 V를 구현하는 형식일 수 있습니다.At run time, the type of a collection element may be the one that derives from T and actually implements V. 그렇지 않은 경우에는 InvalidCastException을 throw합니다.If that's not the case, an InvalidCastException is thrown.

C# 언어 사양C# language specification

자세한 내용은 C# 언어 사양foreach 문 섹션을 참조하세요.For more information, see The foreach statement section of the C# language specification.

C# 8.0 이상에 추가된 기능에 대한 자세한 내용은 다음 기능 제안 노트를 참조하세요.For more information about features added in C# 8.0 and later, see the following feature proposal notes:

참고 항목See also