C# 15 新功能:具標籤的 break 和 continue。
注意:寫作本文時 .NET 11 尚未正式發布,文中的範例程式是以 .NET 11 Preview 7 SDK 編譯。
在撰寫演算法或處理多維矩陣時,巢狀迴圈是極為常見的結構。然而,當我們需要在內層迴圈滿足特定條件時「直接跳出整個外層迴圈」或「跳過當前列直接前進外層下一輪」,傳統 C# 的控制流程往往顯得笨重。
傳統多層迴圈的跳脫痛點
假設我們在一個二維網格中搜尋特定目標,一旦找到就要立即中斷整個搜尋。在 C# 15 之前,開發者通常只有兩種選擇:
第一種是引入額外的布林旗標(boolean flag):
bool found = false;
for (int r = 0; r < rows; r++)
{
for (int c = 0; c < cols; c++)
{
if (grid[r, c].IsTarget)
{
found = true;
break; // 只能跳出內層迴圈
}
}
if (found)
break; // 外層還得再檢查一次旗標並 break
}這種寫法雖然合乎結構化規範,但旗標變數污染了上下文,且每多一層巢狀迴圈就得逐層檢查旗標,既冗贅又容易遺漏。
第二種做法是使用 goto 陳述式:
for (int r = 0; r < rows; r++)
{
for (int c = 0; c < cols; c++)
{
if (grid[r, c].IsTarget)
goto Found; // 直接跳到迴圈外標籤
}
}
Found:
// 繼續後續處理雖然 goto 乾脆俐落,但其任意跳躍的特性容易破壞程式碼結構,在許多團隊的程式碼規範中被視為禁忌或發出靜態分析警告。
具標籤的 break 與 continue
為了解決這個長年痛點,C# 15 引入了具標籤的跳躍陳述式(labeled break and continue)。
現在,你可以直接在迴圈關鍵字(for、foreach、while、do)前方加上標籤名稱與冒號,隨後在內層迴圈中使用 break <標籤> 或 continue <標籤> 來精確控制目標迴圈:
searchLoop: for (int r = 0; r < rows; r++)
{
for (int c = 0; c < cols; c++)
{
if (grid[r, c].IsObstacle)
continue searchLoop; // (1) 跳過本列剩餘單元格,直接推進到外層下一列
if (grid[r, c].IsTarget)
{
targetPosition = (r, c);
break searchLoop; // (2) 直接跳出整個 searchLoop 外層迴圈
}
}
}說明:
- 當遇到障礙物時,
continue searchLoop;會直接使外層的r迴圈進入下一次迭代(r++),省去內層多餘的判斷。 - 當尋獲目標時,
break searchLoop;能一舉跳離整個外層迴圈,既不需額外宣告found旗標,也沒有goto的非結構化跳躍隱患。
注意事項
具標籤的
break與continue依然受到嚴格的結構化程式作用域保護:
- 標籤只能附加在迴圈陳述式前方。
- 跳躍目標必須是包含當前陳述式的外層封閉迴圈;你不能跳躍至同層、子層或毫無關聯的其他迴圈。
- 若巢狀層級超過兩層,實務上通常更推薦將搜尋邏輯抽取成獨立函式並使用
return提早結束,以維持函式職責的單純與可讀性。
本文摘自《現代 C# 精要》第二版 (beta)。本書尚未正式出版,這裡摘錄的是 beta 版內容。
沒有留言: