windows C#-弃元(下)

对具有 out 参数的方法的调用

当调用 Deconstruct 方法来析构用户定义类型(类、结构或接口的实例)时,可使用占位符表示单个 out 参数的值。 但当使用 out 参数调用任何方法时,也可使用弃元表示 out 参数的值。

以下示例调用 DateTime.TryParse(String, out DateTime) 方法来确定日期的字符串表示形式在当前区域性中是否有效。 因为该示例侧重验证日期字符串,而不是解析它来提取日期,所以方法的 out 参数为占位符。

string[] dateStrings = ["05/01/2018 14:57:32.8", "2018-05-01 14:57:32.8",
                      "2018-05-01T14:57:32.8375298-04:00", "5/01/2018",
                      "5/01/2018 14:57:32.80 -07:00",
                      "1 May 2018 2:57:32.8 PM", "16-05-2018 1:00:32 PM",
                      "Fri, 15 May 2018 20:10:57 GMT"];
foreach (string dateString in dateStrings)
{
    if (DateTime.TryParse(dateString, out _))
        Console.WriteLine($"'{dateString}': valid");
    else
        Console.WriteLine($"'{dateString}': invalid");
}
// The example displays output like the following:
//       '05/01/2018 14:57:32.8': valid
//       '2018-05-01 14:57:32.8': valid
//       '2018-05-01T14:57:32.8375298-04:00': valid
//       '5/01/2018': valid
//       '5/01/2018 14:57:32.80 -07:00': valid
//       '1 May 2018 2:57:32.8 PM': valid
//       '16-05-2018 1:00:32 PM': invalid
//       'Fri, 15 May 2018 20:10:57 GMT': invalid
独立弃元

可使用独立弃元来指示要忽略的任何变量。 一种典型的用法是使用赋值来确保一个参数不为 null。 下面的代码使用弃元来强制赋值。 赋值的右侧使用 Null 合并操作符,用于在参数为 null 时引发 System.ArgumentNullException。 此代码不需要赋值结果,因此将对其使用弃元。 该表达式强制执行 null 检查。 弃元说明你的意图:不需要或不使用赋值结果。

public static void Method(string arg)
{
    _ = arg ?? throw new ArgumentNullException(paramName: nameof(arg), message: "arg can't be null");

    // Do work with arg.
}

以下示例使用独立占位符来忽略异步操作返回的 Task 对象。 分配任务的效果等同于抑制操作即将完成时所引发的异常。 这使你的意图更加明确:你需要对 Task 使用弃元,并忽略该异步操作生成的任何错误。

private static async Task ExecuteAsyncMethods()
{
    Console.WriteLine("About to launch a task...");
    _ = Task.Run(() =>
    {
        var iterations = 0;
        for (int ctr = 0; ctr < int.MaxValue; ctr++)
            iterations++;
        Console.WriteLine("Completed looping operation...");
        throw new InvalidOperationException();
    });
    await Task.Delay(5000);
    Console.WriteLine("Exiting after 5 second delay");
}
// The example displays output like the following:
//       About to launch a task...
//       Completed looping operation...
//       Exiting after 5 second delay

如果不将任务分配给弃元,则以下代码会生成编译器警告:

private static async Task ExecuteAsyncMethods()
{
    Console.WriteLine("About to launch a task...");
    // CS4014: Because this call is not awaited, execution of the current method continues before the call is completed.
    // Consider applying the 'await' operator to the result of the call.
    Task.Run(() =>
    {
        var iterations = 0;
        for (int ctr = 0; ctr < int.MaxValue; ctr++)
            iterations++;
        Console.WriteLine("Completed looping operation...");
        throw new InvalidOperationException();
    });
    await Task.Delay(5000);
    Console.WriteLine("Exiting after 5 second delay");

如果使用调试器运行前面两个示例中的任意一个,则在引发异常时,调试器将停止该程序。 在没有附加调试器的情况下,这两种情况下的异常都会被以静默方式忽略。

_ 也是有效标识符。 当在支持的上下文之外使用时,_ 不视为占位符,而视为有效变量。 如果名为 _ 的标识符已在范围内,则使用 _ 作为独立占位符可能导致:

1. 将预期的占位符的值赋给范围内 _ 变量,会导致该变量的值被意外修改。 例如:

private static void ShowValue(int _)
{
   byte[] arr = [0, 0, 1, 2];
   _ = BitConverter.ToInt32(arr, 0);
   Console.WriteLine(_);
}
 // The example displays the following output:
 //       33619968

2. 因违反类型安全而发生的编译器错误。 例如:

private static bool RoundTrips(int _)
{
   string value = _.ToString();
   int newValue = 0;
   _ = Int32.TryParse(value, out newValue);
   return _ == newValue;
}
// The example displays the following compiler error:
//      error CS0029: Cannot implicitly convert type 'bool' to 'int'

编译器错误 CS0136:“无法在此范围中声明名为 "_" 的局部变量或参数,因为该名称用于在封闭的局部范围中定义局部变量或参数”。例如:

public void DoSomething(int _)
{
 var _ = GetValue(); // Error: cannot declare local _ when one is already in scope
}
// The example displays the following compiler error:
// error CS0136:
//       A local or parameter named '_' cannot be declared in this scope
//       because that name is used in an enclosing local scope
//       to define a local or parameter
上一篇:如何在 Linux 服务器上安装 Git


下一篇:虚拟化负载均衡至少需要几台服务器?