底線標記(_)表示不需要某個值。 其確切含義取決於出現地點:
| Context |
_ 的意義 |
|---|---|
| 切換式表達臂或巢狀模式 | 一個匹配但不捕捉結果的棄置模式 |
解構或 out 論證 |
一個忽略已產生值的捨棄項 |
像是 _ = expression 這樣的指派 |
會評估運算式並忽略其結果的 捨棄指定 |
兩個或以上 lambda 參數,稱為 _ |
捨棄 那些未被使用的參數 |
var _ 呈現某種模式 |
var帶有棄牌標記的圖案 |
這些形式在拼寫和意圖上相同,但不能互換。
使用 switch 進行模式比對
在下列範例中, statusCode 是 int。 每個開關臂會產生 string 訊息,程式會寫入主控台。 最後一個 _ 會處理除了 404 和 200 以外的所有狀態碼:
static void ShowStatus()
{
int statusCode = 503;
string message = statusCode switch
{
200 => "Ready",
404 => "Not found",
_ => "Another status"
};
Console.WriteLine(message);
}
捨棄模式會套用至輸入運算式。 C# 會評估該運算式,而 _ 會比對評估後的值,但不會擷取該值。 當所有先前未處理的值都應採用相同的後援處理時,請選擇 _ 作為 switch 運算式的最後一個 arm。 把它放在最後,因為它符合所有條件,包括 null。
該形式 var _ 為帶有捨棄標示的 var 模式。 它也會匹配所有評估值,但不會引入可讀變數。 對於 switch 的 catch-all,請優先使用較短的 _ 捨棄模式。 欲了解更多模式 var 與指定,請參見 宣告、常數及 var 模式。
解構聲明
GetForecast 回傳一個包含四個成分的元組:一座 string 城市,以及三個 int 高溫、低溫和降雨機率的值。 解構宣告會保留 city 和 high,因為程式會顯示它們。 它用 _ 來表示低溫和降雨機率,因為命名這些未使用的元件會表示程式碼需要它們:
static void ShowForecast()
{
var (city, high, _, _) = GetForecast();
Console.WriteLine($"{city}: high {high}°C");
static (string City, int High, int Low, int RainChance) GetForecast() =>
("Portland", 18, 9, 40);
}
當物件的 Deconstruct 方法會產生數個值時,相同的捨棄語法同樣適用。 關於這些形式,請參見 「解構元組及其他類型」。
呼叫具有 out 參數的方法
假設輸入欄位只在表示整數時接受文字。 該 TryParse(String, Int32) 方法回傳 a bool ,報告解析是否成功。 它也會透過參數out產生解析結果int。 以下程式碼只需布林結果即可接受或拒絕輸入:
static void CheckInput()
{
string text = "42";
if (IsWholeNumber(text))
{
Console.WriteLine($"Accepted: {text}");
}
else
{
Console.WriteLine("Enter a whole number.");
}
static bool IsWholeNumber(string text) => int.TryParse(text, out _);
}
只有手術成功才重要時才會使用 out _ 。 捨棄項清楚表明不需要剖析出的數字。 如果後續程式碼需要這個數字,請給 out 參數命名,例如 out int number,並保留該值。
棄置指派 _ = expression,評估一個表達式,並故意忽略其結果。 當這個表達本身不是一個有效的陳述時,它偶爾會派上用場。
Important
不要在應用程式程式碼中使用 _ = Task.Run(...) 或 _ = SomeAsyncMethod() 捨棄任務。 等待該工作完成,讓其完成結果與例外狀況都保留在呼叫流程中。 棄置指派不會讓任務安全、觀察例外,或建立支援的「執行後忘記」操作。
標記未使用的lambda參數
一個 EventHandler 會接收一個 object? 傳送端和一個 EventArgs 值。 以下處理器不需要任何參數;它只會寫 "Timer tick" 入主控台。 同時命名兩個參數 _ ,使其未使用的狀態可見,而不必創造身體從未使用過的名稱:
static void ShowLambdaDiscards()
{
EventHandler handler = (_, _) => Console.WriteLine("Timer tick");
handler(null, EventArgs.Empty);
}
當委派簽章需要 Lambda 主體未使用的輸入參數時,請選擇捨棄參數。 若 lambda 只有一個名為 _的參數, _ 則仍為向後相容的普通參數名稱。
避免 _ 作為識別碼
_ 在 C# 無法辨識丟棄的情境中,可以是普通的識別碼。 在範圍內命名 _ 的變數可能會收到看起來像棄置指派的賦值。 在模式內容中,名為 _ 的可存取常數或型別也可能改變 _ 的解讀方式。 避免自行宣告名稱為 _ 的變數、常數或型別;請使用 _ 來表達捨棄意圖。