C# 中的模式匹配
模式匹配是测试表达式是否具有某一特性的方法。C# 提供了非常简洁优雅的语法用于匹配模式并在匹配时执行相应的操作。
检查匹配
模式匹配最高频的场景是确保值不为 null。
public void IsMatch(int? number) { if (number is int n) { Console.WriteLine(#34;参数 ‘number’ 具有值{n}”); } else { Console.WriteLine(“参数值为null”); } }
上述代码使用 is 检查 number 是否有值,若有,则赋给新变量 n。注意,新变量仅在 if 语句块中有效。
离散值匹配
检查参数是否等于指定的值。支持的类型包括字符串和枚举,从 C# 11 开始,还支持 Span 和 ReadOnlySpan。
public string ConstantMatch(string? name) => name switch { “张三” => “我是张三”, “李四” => “我是李四”, _ => #34;我不知道自己是谁” }; public string ConstantMatch(ReadOnlySpan name) => name switch { “张三” => “我是张三”, “李四” => “我是李四”, _ => #34;我不知道自己是谁” };
上面的代码,根据 type 参数的值来返回不同的字符串。弃用符号 _ 表示未在类表中定义的任意其它值,包括 null。
类型匹配
模式匹配的另一用途是检查值是否与给定类型匹配。
public string TypeMatch(Animal? animal) => animal switch { Cat => “发现喵咪一只”, Dog => “发现汪汪一只”, null => “毛都没发现”, _ => #34;发现不知道是啥的一个东西” };
上面的代码,根据 animal 参数的实际类型返回不同的字符串。弃元符号 _ 表示未列出的任意其它值。
关系匹配
关系匹配可以将数值与常量进行比较。
public string RelationalMatch(int age) => age switch { “婴儿”, “幼儿”, “儿童”, “少年”, _ => “成年” };
上述代码根据 age 的值大小返回不同的值。弃元符号 _ 表示未列出的任意其它值。
关系匹配模式还可以使用 and 和 or 来组合条件。
public static string GetWaterState(int temperature) => temperature switch { (> 0) and ( “液体”, “固体”, > 100 => “气体”, 0 => “固体/液体临界点”, 100 => “液体/气体临界点”, };
属性匹配
还可以对指定对象的属性进行匹配,可以实现多个参数同时检查。
public record Order(int Items, decimal Cost); public decimal CalculateDiscount(Order order) => order switch { (Items: > 10, Cost: > 1000.00m) => 0.10m, (Items: > 5, Cost: > 500.00m) => 0.05m, Order { Cost: > 250.00m } => 0.02m, null => throw new ArgumentNullException(nameof(order)), var someObject => 0m, };
上面的代码中,前两项检查 Items 和 Cost 属性的值。第三项只检查了 Cost 属性的值。第四项检查是否为 null,第五项匹配任意其它值。