C# 中的弃元(Discards)模式

C# 7.0 引入了一个新的特性叫弃元(Discards),弃元本质上是一个变量占位符,用于忽略开发者不感兴趣的值,相等于未赋值的变量。

方法调用时使用启元

有些方法有 out 参数,但若我们实际无需使用 out 值,就可以使用弃元模式忽略该变量。

 if (DateTime.TryParse("02/29/2019", out DateTime result))
 {
     Console.WriteLine("正确的日期格式");
 }
 else
 {
     Console.WriteLine("不正确的日期格式");
 }

上面的代码中,result 实际上没有任何作用,这时候就可以用弃元模式,忽略 result 的值。

 if (DateTime.TryParse("02/29/2019", out DateTime _))
 {
     Console.WriteLine("正确的日期格式");
 }
 else
 {
     Console.WriteLine("不正确的日期格式");
 }

_ 的类型可以由编译器推断出来,可以省略。

 if (DateTime.TryParse("02/29/2019", out _))
 {
     Console.WriteLine("正确的日期格式");
 }
 else
 {
     Console.WriteLine("不正确的日期格式");
 }

在元组和对象解构中使用弃元模式

如果只使用元组元素中的一部分,可以使用弃元模式。

 public static (string Name, int Age, int Score) GetStudent()
 {
     var name = "小红";
     var age = 13;
     var score = 90;
     return (name, age, score);
 }
 
 // 只对名称和年龄感兴趣
 var (name, age, _) = student;
 
 // 只对名称和分数感兴趣
 var (name, _, score) = student;
 
 // 只对名称感兴趣
 var (name, _, _) = student;
 

上述 GetStudent() 返回一个包含学生姓名、年龄、成绩的元组,三个赋值语句演示了解构元组时使用弃元对象忽略不需要的元素。

类和结构通过 Deconstruct() 方法可以支持结构语法,同样可以使用弃元符号。

 public class Student
 {
     public string Name { get; set; } = default!;
     public int Age { get; set; }
     public int Score { get; set; }
     public void Deconstruct(out string name, out int age, out int score)
     {
         name = Name;
         age = Age;
         score = Score;
     }
 }
 
 var student = new Student() { Name = "小红", Age = 13, Score = 90 };
 // 使用解构语法将对象解构到变量,score 被忽略
 var (name, age, _) = student;

模式匹配中使用弃元

在模式匹配中,_ 弃元可以匹配所有类型,包括 null,实际效果就是表示所有未在列表中列出的其它匹配项。如果表达式其余各项不完备,且省略弃元项,编译器会报错,提示 switch 表达式没有覆盖所有可能的值。

 
 public string TypeMatch(Animal? animal) => animal switch
 {
     Cat => "发现喵咪一只",
     Dog => "发现汪汪一只",
     null => "毛都没发现",
     _ => #34;发现不知道是啥的一个东西"
 };

独立使用弃元

也可以独立使用启元符号表示忽略某一个特定变量。一个比较典型使用场景是通过空合运算符确保参数不为 null 时使用。

 public static void Method(string arg)
 {
     _ = arg ?? throw new ArgumentNullException(nameof(arg));
     // ...
 }

以下代码使用启元模式忽略了异步方法返回的 Task 对象,以及由此异步过程产生的任何错误。

 public static async Task ExecuteAsyncMethods()
 {
     Console.WriteLine("即将执行");
     _ = 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);
 }

如果不添加弃元符号,则编译器会报错: 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.

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章