首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> C# 入門

C# 迴圈完整指南:for/while/do-while/foreach、跳脫控制、無限迴圈與效能最佳化

     編輯:C# 入門

C# 迴圈完整指南:for/while/do-while/foreach、跳脫控制、無限迴圈與效能最佳化

迴圈 讓程式重複執行程式碼區塊。C# 提供四種主要迴圈結構,各有適用場景。掌握迴圈語法、跳脫控制、效能特性,能寫出清晰、高效的演算法實作。

四大迴圈結構對照

迴圈類型判斷時機適用場景關鍵字
for每次迭代前已知迭代次數、索引存取、計數器控制for(init; cond; step)
foreach每次迭代前遍歷集合/陣列、唯讀存取、簡潔語法foreach(var x in coll)
while每次迭代前未知次數、條件複雜、前置檢查while(cond)
do-while每次迭代後至少執行一次、選單系統、輸入驗證do { } while(cond);

for 迴圈:完全控制

// 標準形式
for (int i = 0; i < 10; i++) {
    Console.WriteLine(i);
}

// 多變數初始化/遞增
for (int i = 0, j = 10; i < j; i++, j--) {
    Console.WriteLine($"{i}, {j}");
}

// 省略區段 (需保留分號)
int k = 0;
for (; k < 5; ) { // 僅條件
    Console.WriteLine(k++);
}

// 無限迴圈
for (;;) { /* 需 break 跳出 */ }

foreach 迴圈:遍歷集合

適用於實作 IEnumerable/IEnumerable<T> 的型別:陣列、List、Dictionary、自訂集合。

int[] numbers = {1, 2, 3, 4, 5};
foreach (int n in numbers) {
    Console.WriteLine(n);
}

// 唯讀:無法修改迭代變數
// n = 10; // 編譯錯誤

// 字典遍歷
var dict = new Dictionary { ["a"] = 1, ["b"] = 2 };
foreach (var (key, value) in dict) { // C# 7+ 解構
    Console.WriteLine($"{key} = {value}");
}

// 索引需求:用 for 或 索引值元組
foreach (var (index, value) in numbers.Select((v, i) => (i, v))) { }

注意:foreach 對陣列/List 使用索引器,無列舉器配置開銷;對一般 IEnumerable 會建立列舉器。

while 迴圈:條件驅動

int n = 10;
while (n > 0) {
    Console.WriteLine(n--);
}

// 複雜條件
string? input;
while ((input = Console.ReadLine()) != "exit") {
    Process(input);
}

// 旗標控制
bool running = true;
while (running) {
    running = GameLoop();
}

do-while 迴圈:至少一次

string? input;
do {
    Console.Write("輸入指令: ");
    input = Console.ReadLine();
    Process(input);
} while (input != "quit");

// 選單系統經典用法
int choice;
do {
    ShowMenu();
    choice = ReadInt();
    Execute(choice);
} while (choice != 0);

迴圈控制陳述式

break:立即離開迴圈

for (int i = 0; i < 100; i++) {
    if (i == 42) break; // 只執行到 41
    Console.WriteLine(i);
}

// 搜尋找到即停止
foreach (var item in items) {
    if (item.Matches(criteria)) {
        found = item;
        break;
    }
}

continue:跳過本次迭代,直接進入下一次判斷

for (int i = 0; i < 10; i++) {
    if (i % 2 == 0) continue; // 跳過偶數
    Console.WriteLine(i); // 只印奇數 1,3,5,7,9
}

// 守衛子句風格
foreach (var file in files) {
    if (!file.Exists) continue;
    if (file.Size == 0) continue;
    Process(file);
}

goto、return、throw 也可離開迴圈

goto 可跳出多層巢狀迴圈(慎用),return 直接離開方法,throw 拋出例外。

巢狀迴圈與標籤

// 雙重迴圈搜尋
outer:
for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
        if (matrix[i, j] == target) {
            Console.WriteLine($"Found at ({i},{j})");
            break outer; // 跳出外層迴圈
        }
    }
}

無限迴圈模式

// 1. for(;;) - 慣用寫法
for (;;) {
    var task = queue.Dequeue();
    if (task == null) break;
    task.Execute();
}

// 2. while(true) - 語意明確
while (true) {
    if (cancellationToken.IsCancellationRequested) break;
    DoWork();
}

// 3. 事件驅動迴圈
while (await channel.Reader.WaitToReadAsync()) {
    while (channel.Reader.TryRead(out var item)) {
        Process(item);
    }
}

效能最佳化

場景建議原因
陣列/List 索引存取for 迴圈避免列舉器、邊界檢查消除、向量化
唯讀遍歷foreach語法簡潔、陣列/List 無配置、語意明確
需修改集合大小反向 for 或 List.RemoveAll避免索引錯位、foreach 中修改拋例外
熱路徑大量迭代for + Span<T>零配置、SIMD 向量化、快取友善
LINQ 鏈式注意延遲執行、多次列舉必要時 .ToArray() 具體化

進階:迭代器與 yield return

// 自訂迴圈序列
IEnumerable Fibonacci(int count) {
    int a = 0, b = 1;
    for (int i = 0; i < count; i++) {
        yield return a;
        (a, b) = (b, a + b);
    }
}

// 使用:延遲執行、串流處理
foreach (var n in Fibonacci(10).Take(5)) { } // 只產生前 5 個

最佳實踐

  • 選擇正確迴圈:已知次數/索引 → for;遍歷集合 → foreach;條件驅動 → while;至少一次 → do-while。
  • 避免深層巢狀:超過 3 層提取方法、用 LINQ、或扁平化演算法。
  • 迴圈不變式外提:不變計算、物件建立、方法呼叫移出迴圈。
  • 使用 break/continue 簡化邏輯:守衛子句減少縮排層級。
  • 非同步迴圈:await foreach (IAsyncEnumerable)、Parallel.ForEachAsync。
  • 大量資料分批處理:避免記憶體壓力,用 Batch/Chunk (NET 6+)。

常見問題 FAQ

Q: foreach 可以修改集合元素嗎?

A: 迭代變數唯讀,但若元素為參考型別,可修改其內容(如 item.Name = "new")。不可修改集合結構(增/刪),否則拋 InvalidOperationException。

Q: for vs foreach 效能差異?

A: 陣列/List foreach 編譯器最佳化為索引存取,效能相近。一般 IEnumerable foreach 有列舉器配置。熱路徑基準測試為準。

Q: 如何跳出多層迴圈?

A: 1) goto label 2) 提取方法用 return 3) 旗標變數 4) 例外 (不建議)。goto 在此場景可接受。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved