购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

4.13 模式

在第3章中,我们展示了如何使用 is 运算符验证引用的转换是否成功:

以上代码可以更加简洁地写为:

以上代码引入了一种称为类型模式的模式。除了类型模式之外, is 运算符还支持其他在C#最近几个版本中引入的模式。例如,属性模式:

模式可以在以下上下文中使用:

· is 运算符之后( variable is pattern )。

· switch语句中。

· switch表达式中。

我们在2.11.3.5和3.2.2.4节中介绍了类型模式(并简要介绍了元组模式)。本节将介绍更多C#最近版本中引入的高级模式。

大多数特定模式都是随switch语句或表达式一起使用的。这些模式可以减少 when 子句的使用,也可以在原本无法支持的场景下使用switch。

本节介绍的模式在某些场景下是有一定作用的。但请牢记这些高度模式化的switch语句都可以被简单的 if 语句——或者在某些情况下还可以使用三元运算符——来替代,而且替换后的代码量并不会显著增加。

4.13.1 var模式

var模式是类型模式的变体,即将类型名称替换为了 var 关键字。由于转换必定成功,因此它的目的仅仅是引入一个可以重复使用的变量:

上述代码等价于以下代码:

能够在表达式体方法中使用var模式引入一个可复用的变量(本例中为 upper )的确方便。但是该模式只能在方法返回类型为 bool 时使用。

4.13.2 常量模式

常量模式可以直接与常量进行匹配,常用于处理 object 类型:

以上示例中的粗体文字等价于:

(C#无法直接使用 == 比较 object 与常量的值,因为运算符是静态的,编译器需要提前知道对象的类型。)

因此,这种模式仅在没有合理替代方案的情况下才有少许的用处:

常量与模式组合器共同使用可以发挥更大的作用,我们稍后将进行介绍。

4.13.3 关系模式

C# 9支持在模式中使用 < > <= >= 运算符:

这种模式适合与 switch 配合使用:

关系模式可以和模式组合器共同使用以发挥更大作用。

关系模式也可以和编译时类型为 object 的变量配合使用。但若和数值常量一起使用则需要特别注意。在以下示例中,最后一行将输出False,因为我们试图匹配decimal(十进制)值与整数值:

4.13.4 模式组合器

从C# 9开始,我们可以通过 and or not 关键字将模式组合起来:

&& || 运算符类似, and or 拥有更高的优先级。我们也可以使用括号更改运算顺序。

我们可以将 not 组合器与类型模式巧妙结合,测试对象是否是特定类型:

这比下列写法要好懂得多:

4.13.5 元组模式和位置模式

元组模式(C# 8引入)用于匹配元组:

这种模式可用于switch多个值:

元组模式可以理解为位置模式(C# 8+)的一种特殊形式。位置模式可以匹配任何定义了 Deconstruct 方法(请参见3.1.5节)的类型。在以下示例中,我们利用了编译器为 Point 记录生成的解构器:

在匹配的过程中可以同时进行解构操作,使用以下语法:

以下 switch 表达式结合使用了类型模式和位置模式:

4.13.6 属性模式

属性模式(C# 8)可以匹配对象的一个或者多个属性值。例如,在介绍 is 运算符时我们曾给出以下示例:

但是,上述代码相比以下代码并没有显著的优势:

但是将属性模式与swtich语句和表达式联合使用优势就明显了。以 System.Uri 类为例(这个类表示一个URI),这个类定义了 Scheme Host Port IsLoopback 属性。在以下防火墙代码中,我们可以使用switch表达式配合属性模式来决定是否允许访问特定的URI:

属性模式支持属性嵌套,因此以下代码是合法的:

而上述代码在C# 10中可以进一步简化为:

还可以在属性模式中使用其他模式,包括使用关系模式:

而更详细的条件可以使用 when 子句来表示:

将属性模式和类型模式结合也是可行的:

就像类型模式那样,以上用法也可以在子句的末尾引入变量,并使用该变量的值:

该变量也可以在 when 子句中使用:

属性模式中甚至可以在属性一级引入变量:

新引入的变量可以使用隐式类型,因此我们可以将 string 替换为 var 。以下是完整的示例代码:

想要找到一个通过上述模式而令代码变得更加简洁的例子并不容易。与上述代码相比,以下两种实现方式的代码反而更短:

或者 uI7gIhbKTVbMHRR6dc7jFEOvL4nObLtBuFGs0fPswmiRqQmIqRDXvAbBE3lfCgFC

点击中间区域
呼出菜单
上一章
目录
下一章
×