增强的模式匹配
C#9.0添加了几种新的模式。我们可以参阅模式匹配教程 ,来了解下面代码的上下文:
1 public static decimal CalculateToll(object vehicle) => 2 vehicle switch 3 { 4 ... 5 6 DeliveryTruck t when t.GrossWeightClass > 5000 => 10.00m + 5.00m, 7 DeliveryTruck t when t.GrossWeightClass < 3000 => 10.00m - 2.00m, 8 DeliveryTruck _ => 10.00m, 9 10 _ => throw new ArgumentException("Not a known vehicle type", nameof(vehicle)) 11 };
1、简单类型模式(Simple type patterns)
当前,进行类型匹配的时候,一个类型模式需要声明一个标识符——即使这标识符是一个弃元_,像上面代码中的DeliveryTruck_
。但是在C#9.0中,你可以只写类型,如下所示:
1 DeliveryTruck => 10.00m,
2、关系模式(Relational patterns)
C#9.0 提出了关系运算符<,<=等对应的模式。所以你现在可以将上面模式中的DeliveryTruck部分写成一个嵌套的
switch表达式:
1 DeliveryTruck t when t.GrossWeightClass switch 2 { 3 > 5000 => 10.00m + 5.00m, 4 < 3000 => 10.00m - 2.00m, 5 _ => 10.00m, 6 },
这里 > 5000
和 < 3000就是关系模式。
3、
逻辑模式(Logical patterns)
最后,你可以用逻辑操作符and,or 和not将模式进行组合,这里的操作符用单词来表示,是为了避免与表达式操作符引起混淆。例如,上面嵌套的的switch示例,可以按照如下升序排序:
1 DeliveryTruck t when t.GrossWeightClass switch 2 { 3 < 3000 => 10.00m - 2.00m, 4 >= 3000 and <= 5000 => 10.00m, 5 > 5000 => 10.00m + 5.00m, 6 },
此例中间的分支使用了and 来组合两个关系模式来形成了一个表达区间的模式。
not模式的常见的使用是将它用在null常量模式上,如not null。例如我们要根据是否为空来把一个未知分支的处理进行拆分:
1 not null => throw new ArgumentException($"Not a known vehicle type: {vehicle}", nameof(vehicle)), 2 null => throw new ArgumentNullException(nameof(vehicle))
此外,not
在 if
条件中包含 is
表达式时将会很方便,可以取代笨拙的双括号,例如:
if (!(e is Customer)) { ... }
你可以写成:
if (e is not Customer) { ... }
实际上,在is not表达式里,允许你给Customer指定名称,以便后续使用。
1 if (e is not Customer c) { throw ... } // 如果这个分支抛出异常或者返回... 2 var n = c.FirstName; // ... 这里,c肯定已经被赋值了,不会为空