下划线标记(_)表示不需要某个值。 其确切含义取决于其显示位置:
| 上下文 |
_ 的含义 |
|---|---|
| 开关表达式臂或嵌套模式 | 匹配时不捕获结果的弃元模式 |
解构或 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 表达式的最后一个分支。 把它放在最后,因为它会匹配所有内容,包括 null。
形式 var _ 是一种带有 var 弃元指示符的模式。 它还匹配每个计算值,但它不会引入可读变量。 对于 switch 兜底分支,优先使用较短的 _ 弃元模式。 有关模式和指定的详细信息 var ,请参阅 声明、常量和 var 模式。
解构声明
GetForecast返回一个元组,其中包含四个组成部分:一个城市和三int个string值,用于高温、低温和雨量。 解构声明会保留 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) 方法返回一个 bool,用于指示解析是否成功。 它还通过其 int 参数生成解析后的 out。 以下代码只需要布尔结果才能接受或拒绝输入:
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# 不将其识别为弃元的上下文中,可以是普通标识符。 命名 _ 的作用域内变量可以接收类似于放弃赋值的赋值。 在模式上下文中,名为 _ 的可访问常量或类型还可能会改变对 _ 的解释方式。 避免自行声明名称为 _ 的变量、常量或类型;请使用 _ 表示丢弃意图。