迭代語句 -
使用迭代語句反覆執行一個語句或一組語句。 當指定的布爾表示式評估為for時,會執行其程式碼。
foreach語句會列舉集合的元素,並針對集合的每個元素執行其主體。
do語句依條件執行其主體一次或多次。
while語句根據條件執行其程式碼區段零次或多次。
在迭代語句的正文中,你可以使用該 break 語句退出迴圈。 你可以透過使用這個continue陳述來跳進迴圈中的下一個迭代。
C# 語言參考資料記錄了 C# 語言最新版本。 同時也包含即將推出語言版本公開預覽功能的初步文件。
文件中標示了語言最近三個版本或目前公開預覽版中首次引入的任何功能。
小提示
欲查詢某功能何時首次在 C# 中引入,請參閱 C# 語言版本歷史的條目。
for 陳述式
當指定的布爾表達式評估為 for 時,true 將執行單一語句或語句區塊。 下列範例顯示 for 在整數計數器小於三時執行的語句:
for (int i = 0; i < 3; i++)
{
Console.Write(i);
}
// Output:
// 012
上述範例顯示 語句的 for 元素:
初始 化器 區段,只執行一次,然後進入迴圈。 一般而言,您會在該區段中宣告並初始化區域迴圈變數。 你無法從語句外部
for存取宣告的變數。上述範例中的 初始化運算式 區段會宣告並初始化整數計數器變數:
int i = 0條件區段決定迴圈中是否執行下一個迭代。 如果評估到 或
true不存在,下一個迭代就會執行。 否則,迴路就會結束。 條件區段必須是布爾表達式。上述範例中的 condition 區段會檢查計數器值是否小於三個:
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> 介面的型別實例中的每個項目,執行語句或語句區塊,如下列範例所示:
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 不限於這些類型。 您可以將它與符合下列條件的任何類型實例搭配使用:
- 類型具有公共無參數
GetEnumerator方法。 此GetEnumerator方法可作為 擴展方法。 - 方法的
GetEnumerator傳回型別具有公用Current屬性和無參數的公用MoveNext方法,其傳回型別為bool。
下列範例會使用foreach語句,搭配System.Span<T>型別的實例,但不會實作任何介面:
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。
等待 foreach
使用該 await foreach 語句來消耗非同步資料流,也就是實作 IAsyncEnumerable<T> 介面的集合類型。 迴圈的每次迭代都可以暫停,等待下一個元素非同步擷取。 下列範例示範如何使用 await foreach 語句:
await foreach (var item in GenerateSequenceAsync())
{
Console.WriteLine(item);
}
您也可以將 await foreach 語句與符合下列條件的任何類型實例搭配使用:
- 類型具有公共無參數
GetAsyncEnumerator方法。 此方法可作為 延伸成員。 - 方法的
GetAsyncEnumerator傳回型別有公用Current屬性和公用無參數MoveNextAsync方法,其傳回型別為Task<bool>、ValueTask<bool>或任何其他可等待型別,且其 awaiter 的GetResult方法傳回bool值。
預設情況下,該 await foreach 陳述式會處理擷取上下文中的串流元素。 如果您想要停用內容的擷取,請使用 TaskAsyncEnumerableExtensions.ConfigureAwait 擴充方法。 如需同步處理上下文和擷取目前的上下文的詳細資訊,請參閱 取用以工作為基礎的異步模式。 如需異步數據流的詳細資訊,請參閱 異步數據流教學課程。
反覆項目變數的類型
使用 var 關鍵字 讓編譯器推斷陳述中迭代變數 foreach 的型別,如下程式碼所示:
foreach (var item in collection) { }
備註
編譯器可以根據是否啟用可空的可空認知上下文,以及初始化表達式的型別是否為參考型別,推斷宣告的類型var為可空的參考型別。
更多資訊請參見 隱式型別的局部變數。
您也可以明確指定反復項目變數的類型,如下列程式代碼所示:
IEnumerable<T> collection = new T[5];
foreach (V item in collection) { }
在上述形式中,集合元素的型別 T 必須能隱含或明確轉換成迭代變數的型別 V 。 如果從T到V的明確轉換在執行時失敗,foreach語句會拋出InvalidCastException。 例如,如果 T 是非密封類別類型, V 可以是任何介面類型,甚至是未實作的 T 介面類型。 在執行時,集合元素的類型可以是從 T 衍生並實際實作 V的元素。 如果情況並非如此,則會引發 InvalidCastException 。
do 陳述式
當指定的布爾表達式評估為 do 時,true 將執行單一語句或語句區塊。 由於迴圈在每次執行後都會評估該表達式,因此迴 do 圈會執行一次或多次。 迴圈 do 與 while 迴圈不同,迴圈會執行零次或多次。
以下範例展示了此語句的使用方式:do
int n = 0;
do
{
Console.Write(n);
n++;
} while (n < 5);
// Output:
// 01234
while 陳述式
當指定的布爾表達式評估為 while 時,true 將執行單一語句或語句區塊。 由於迴圈在每次執行前都會評估該表達式,迴 while 圈執行次數為零或多。 迴圈 while 與 do 迴圈不同,迴圈會執行一或多次。
以下範例展示了此語句的使用方式:while
int n = 0;
while (n < 5)
{
Console.Write(n);
n++;
}
// Output:
// 01234
C# 語言規格
如需詳細資訊,請參閱 C# 語言規格的下列幾節: