C# 9.0 新特性之模式匹配简化的实现

作者:Liam Wang 时间:2023-11-06 19:42:15 

记得在 MS Build 2020 大会上,C# 语言开发项目经理 Mads Torgersen 宣称 C# 9.0 将会随着 .NET 5 在今年 11 月份正式发布。目前 .NET 5 已经到了 Preview 5 阶段了,C# 9.0 也已经初具规模。忍不住激动的心情,暂停更新《C#.NET 拾遗补漏》系列几天,先要和大家分享一下我了解到的 C# 9.0 的新特性。由于新特性比较多,所以会分成几篇来讲。这是第一篇,专讲模式匹配这个特性的简化。

模式匹配(Pattern Matching)是在 C# 7.0 引入的,是对 switch 语句的增强,可以支持实现复杂的条件匹配。下面我先用一个示例来展示一下模式匹配的一般的用法。

假如现在我们要计算各种车辆在某高速的通行费,比如有下面四种车辆,分别定义为以下四个类,各个类中定义了和通行费计算相关的属性:


public class Car
{
 public int Passengers { get; set; }
}

public class DeliveryTruck
{
 public int GrossWeightClass { get; set; }
}

public class Taxi
{
 public int Fares { get; set; }
}

public class Bus
{
 public int Capacity { get; set; }
 public int Riders { get; set; }
}

下面用用模式匹配的方式来实现一个计算通行费的方法:


public decimal CalculateToll(object vehicle) =>
 vehicle switch
{
 Car { Passengers: 0}    => 2.00m + 0.50m,
 Car { Passengers: 1}    => 2.0m,
 Car { Passengers: 2}    => 2.0m - 0.50m,
 Car c            => 2.00m - 1.0m,

Taxi t => t.Fares switch
 {
   0 => 3.50m + 1.00m,
   1 => 3.50m,
   2 => 3.50m - 0.50m,
   _ => 3.50m - 1.00m
 },

Bus b when ((double)b.Riders / (double)b.Capacity) < 0.50 => 5.00m + 2.00m,
 Bus b when ((double)b.Riders / (double)b.Capacity) > 0.90 => 5.00m - 1.00m,
 Bus b => 5.00m,

DeliveryTruck t when (t.GrossWeightClass > 5000) => 10.00m + 5.00m,
 DeliveryTruck t when (t.GrossWeightClass < 3000) => 10.00m - 2.00m,
 DeliveryTruck _ => 10.00m,

{ } => throw new ArgumentException(message: "Not a known vehicle type", paramName: nameof(vehicle)),
 null => throw new ArgumentNullException(nameof(vehicle))
};

代码来源于文末参考链接

如果上面代码阅读起来感觉吃力,你可以先阅读文末参考链接中的第一个链接,关于模式匹配的详细介绍。

实现这个业务逻辑,若在 C# 7.0 之前,需要用一堆的 if/else 来实现。有了模式匹配后,变得方便了很多,而且使用上很灵活,代码结构也更优美。

对我来说,模式匹配是个极好的特性!但这还不够,C# 9.0 对模式匹配的写法做了进一步的简化!

以上面代码为例,模式匹配可以分为三种:简单模式、关系模式和逻辑模式。下面分别说说 C# 9.0 对三种模式的简化。

简单模式

以上面 CalculateToll 方法示例代码为例,简单模式是这种:


vehicle switch
{
 ...
 Car c => 2.00m - 1.0m
}

我们其实可以发现,上面的变量 c 声明了却没用被使用,现在 C# 9.0 中可以把它省略了:


vehicle switch
{
 ...
 Car => 2.00m - 1.0m
}

关系模式

以上面 CalculateToll 方法示例代码为例,关系模式是通过比较(大小)关系来匹配的,对应的代码片段如下:


DeliveryTruck t when (t.GrossWeightClass > 5000) => 10.00m + 5.00m,
DeliveryTruck t when (t.GrossWeightClass < 3000) => 10.00m - 2.00m,
DeliveryTruck _ => 10.00m,

现在 C# 9.0 可以简写成:


DeliveryTruck t when t.GrossWeightClass switch
{
 > 5000 => 10.00m + 5.00m,
 < 3000 => 10.00m - 2.00m,
 _ => 10.00m,
}

逻辑模式

在 C# 9.0 中,你可以通过逻辑操作符 and、or 和 not 对模式进行组合,下面是一些示例:


DeliveryTruck t when t.GrossWeightClass switch
{
 < 3000 => 10.00m - 2.00m,
 >= 3000 and <= 5000 => 10.00m,
 > 5000 => 10.00m + 5.00m,
}

not null => throw new ArgumentException($"Not a known vehicle type: {vehicle}", nameof(vehicle)),
null => throw new ArgumentNullException(nameof(vehicle))

另外,not 关键字还可以用来替代 if 条件判断中的逻辑非(!),比如:


// 原来的写法
if (!(e is Customer)) { ... }

// 新的写法(易读性更好)
if (e is not Customer) { ... }

C# 9.0 还有很多其它好用的新特性,下一篇文章继续与你分享。文章写短一点不是因为我偷懒哈,而是为了促使大家一次性看完,方便大家在零碎时间阅读,避免因文章太长而成为“收藏不看”系列。

参考:

https://bit.ly/2MNc0DJ
https://bit.ly/2UzEIwu

作者:王亮
出处:http://cnblogs.com/willick
联系:liam.wang@live.com

来源:https://www.cnblogs.com/willick/p/13129012.html

标签:C#9.0,模式匹配
0
投稿

猜你喜欢

  • 详解C# 线程的挂起与唤醒

    2023-03-12 12:40:02
  • 详解C#面相对象编程中的继承特性

    2022-06-09 09:15:24
  • 聊聊Controller中RequestMapping的作用

    2021-12-08 20:48:45
  • 一篇文章带你深入了解javaIO基础

    2022-10-22 21:43:05
  • Android 源码浅析RecyclerView ItemAnimator

    2022-04-20 19:47:41
  • SpringBoot yml配置文件读取方法详解

    2022-12-13 18:04:19
  • idea的spring boot项目实现更改端口号操作

    2023-11-23 03:21:17
  • Android开发AsmClassVisitorFactory使用详解

    2023-07-22 05:34:53
  • Android仿微信之界面导航篇(1)

    2022-07-06 06:59:50
  • C# WinForm实现自动更新程序的方法详解

    2021-12-12 16:19:54
  • android中SwipeRefresh实现各种上拉,下拉刷新示例

    2022-06-14 17:18:03
  • Android圆形头像拍照后“无法加载此图片”的问题解决方法(适配Android7.0)

    2023-11-18 23:26:56
  • 解决Maven中关于依赖导入不进的问题

    2023-09-05 23:13:08
  • 基于Mybatis-plus实现多租户架构的全过程

    2023-08-03 02:10:57
  • java编程题之顺时针打印矩阵

    2022-02-22 04:05:36
  • SpringBoot下如何实现支付宝接口的使用

    2023-11-06 14:26:15
  • java 单例模式的实例详解

    2023-10-08 05:14:08
  • java开发之MD5加密算法的实现

    2022-05-13 23:44:35
  • Linux+Docker+SpringBoot+IDEA一键自动化部署的详细步骤

    2023-08-12 15:25:39
  • C#实现窗口之间的传值

    2022-05-26 08:28:14
  • asp之家 软件编程 m.aspxhome.com