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)
{
    count++;
    Console.WriteLine($"Element #{count}: {element}");
}
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:

  • 型別具有公用無參數 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 具有公用 Current 屬性,以及其傳回型別為的公用無參數 MoveNext 方法 BooleanThe return type of the GetEnumerator method has the public Current property and the public parameterless MoveNext method whose return type is Boolean.

下列範例 foreach 會使用語句 System.Span<T> 搭配類型的實例,而不會執行任何介面: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. 您也可以使用 foreach gotoreturnthrow 語句來結束迴圈。You can also exit a foreach loop by the goto, return, or throw statements.

若將 foreach 陳述式套用到 null,則會擲回 NullReferenceExceptionIf 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) { }

在上述的表單中,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 InvalidCastExceptionIf an explicit conversion from T to V fails at run time, the foreach statement throws an InvalidCastException. 例如,如果 T 是非密封類別型別,則 V 可以是任何介面型別,甚至是不會執行的介面型 T 別。For example, if T is a non-sealed class type, V can be any interface type, even the one that T doesn't implement. 在執行時間,collection 元素的型別可能是衍生自和實際執行的型別 T VAt run time, the type of a collection element may be the one that derives from T and actually implements V. 如果不是這種情況, InvalidCastException 就會擲回。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