反復專案語句 - for
、 foreach
、 do
、 和 while
反復專案語句會重複執行 語句或 語句區塊。 語句:當for
指定的布林運算式評估為 true
時,會執行其主體。 foreach
語句:列舉集合的專案,並針對集合的每個專案執行其主體。 do
語句:有條件地執行其主體一或多次。 while
語句:有條件地執行其主體零次或多次。
在反復專案語句主體內的任何時間點,您可以使用 break 語句來中斷迴圈。 您可以使用 continue 語句,逐步執行迴圈中的下一個反復專案。
for
陳述式
當指定的布林運算式評估為 true
時,for
陳述式會執行某個陳述式或陳述式區塊。 下列範例顯示 for
當整數計數器小於三時,執行其主體的 語句:
for (int i = 0; i < 3; i++)
{
Console.Write(i);
}
// Output:
// 012
上述範例顯示 語句的專案 for
:
在進入迴圈之前,只會執行一次 的初始化運算式 區段。 一般而言,您會在該區段中宣告和初始化局部迴圈變數。 宣告的變數無法從 語句外部
for
存取。上述範例中的 初始化運算式 區段會宣告並初始化整數計數器變數:
int i = 0
條件區段,決定迴圈中的下一個反復專案是否應該執行。 如果評估為
true
或 不存在,則會執行下一個反復專案,否則會結束迴圈。 條件區段必須是布林運算式。上述範例中的 條件 區段會檢查計數器值是否小於三:
i < 3
反覆運算器區段,定義迴圈主體執行之後會發生什麼情況。
上述範例中的 反覆運算器區 段會遞增計數器:
i++
迴圈的主體,必須是 語句或語句區塊。
反覆運算器區段可以包含下列語句運算式的零個或多個,並以逗號分隔:
如果您未在初始化運算式區段中宣告迴圈變數,您也可以在初始化運算式區段中使用上述清單中的零個或多個運算式。 下列範例顯示初始化運算式和反覆運算器區段的數個較不常見的用法:將值指派給初始化運算式區段中的外部變數、叫用初始化運算式和反覆運算器區段中的方法,以及變更反覆運算器區段中兩個變數的值:
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> 介面之型別實例中的每個元素執行 語句或語句區塊,如下列範例所示:
var fibNumbers = new List<int> { 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
語句不限於這些類型。 您可以將它與任何符合下列條件之類型的實例搭配使用:
- 類型具有公用無
GetEnumerator
參數方法。 從 C# 9.0 開始,GetEnumerator
方法可以是類型的 擴充方法。 - 方法的
GetEnumerator
傳回型別具有 publicCurrent
屬性,以及傳回型別為bool
的公用無MoveNext
參數方法。
下列範例會 foreach
使用 語句搭配 類型的實例 System.Span<T> ,但不會實作任何介面:
Span<int> numbers = new int[] { 3, 14, 15, 92, 6 };
foreach (int number in numbers)
{
Console.Write($"{number} ");
}
// Output:
// 3 14 15 92 6
如果列舉值的 Current
屬性傳回參考傳回值 (ref T
其中 T
是集合專案的類型) ,您可以使用 或 ref readonly
修飾詞宣告反復專案變數 ref
,如下列範例所示:
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
陳述式套用到 null
,則會擲回 NullReferenceException。 如果語句的來源集合是空的 foreach
,則不會執行和略過語句的 foreach
主體。
await foreach
您可以使用 await foreach
語句來取用非同步資料流程,也就是實作 IAsyncEnumerable<T> 介面的集合類型。 當非同步擷取下一個專案時,迴圈的每個反復專案可能會暫停。 下列範例示範如何使用 await foreach
語句:
await foreach (var item in GenerateSequenceAsync())
{
Console.WriteLine(item);
}
您也可以搭配 await foreach
任何符合下列條件之類型的實例使用 語句:
- 類型具有公用無
GetAsyncEnumerator
參數方法。 該方法可以是類型的 擴充方法。 - 方法的
GetAsyncEnumerator
傳回型別具有 publicCurrent
屬性,以及傳回型別為Task<bool>
、ValueTask<bool>
的公用無MoveNextAsync
參數方法,或是等候程式GetResult
方法傳回bool
值的任何其他可等候型別。
根據預設,資料流程專案會在擷取的內容中處理。 如果您想要停用內容擷取,請使用 TaskAsyncEnumerableExtensions.ConfigureAwait 擴充方法。 如需同步處理內容和擷取目前內容的詳細資訊,請參閱 使用以工作為基礎的非同步模式。 如需非同步資料流程的詳細資訊,請參閱 非同步資料流程教學課程。
反復專案變數的類型
您可以使用var
關鍵字,讓編譯器推斷 語句中的 foreach
反復專案變數類型,如下列程式碼所示:
foreach (var item in collection) { }
您也可以明確指定反復專案變數的類型,如下列程式碼所示:
IEnumerable<T> collection = new T[5];
foreach (V item in collection) { }
在上述形式中,集合專案的型 T
別必須隱含或明確轉換成反復專案變數的類型 V
。 如果從 到 的明確轉換 T
V
在執行時間失敗,語句會 foreach
擲回 InvalidCastException 。 例如,如果 T
是非密封類別類型, V
可以是任何介面類別型,即使是未實作的 T
介面類別型也一樣。 在執行時間,集合專案的型別可能是衍生自 T
且實際實作 V
的集合專案。 如果不是這種情況, InvalidCastException 則會擲回 。
do
陳述式
當指定的布林運算式評估為 true
時,do
陳述式會執行某個陳述式或陳述式區塊。 因為運算式會在每次迴圈執行後評估,所以 do
迴圈會執行一或多次。 do
語句與while迴圈不同,它會執行零次或多次。
下列範例顯示 語句的使用 do
方式:
int n = 0;
do
{
Console.Write(n);
n++;
} while (n < 5);
// Output:
// 01234
while
陳述式
當指定的布林運算式評估為 true
時,while
陳述式會執行某個陳述式或陳述式區塊。 運算式是在每次執行迴圈之前評估,因此 while
迴圈會執行零次以上。 while
語句與do迴圈不同,它會執行一或多次。
下列範例顯示 語句的使用 while
方式:
int n = 0;
while (n < 5)
{
Console.Write(n);
n++;
}
// Output:
// 01234
C# 語言規格
如需詳細資訊,請參閱 C# 語言規格的下列幾節:
如需 C# 8.0 和更新版本中新增功能的詳細資訊,請參閱下列功能提案附注: