阅读本文大概需要 2 分钟。

记得在 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 中,你可以通过逻辑操作符 andornot 对模式进行组合,下面是一些示例:

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

敬请关注我明天下一篇关于 C# 9.0 新特性的介绍,明天不见不散。

参考:

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

C# 9.0 新特性之模式匹配简化的更多相关文章

  1. C# 7.0 新特性3: 模式匹配

    本文参考Roslyn项目Issue:#206,及Docs:#patterns. 1. C# 7.0 新特性1: 基于Tuple的“多”返回值方法 2. C# 7.0 新特性2: 本地方法 3. C# ...

  2. C# 7.0 新特性1: 基于Tuple的“多”返回值方法

    本文基于Roslyn项目中的Issue:#347 展开讨论. 1. C# 7.0 新特性1: 基于Tuple的“多”返回值方法 2. C# 7.0 新特性2: 本地方法 3. C# 7.0 新特性3: ...

  3. C#7.0&6.0新特性 — 完整版

    C#2.0 泛型 部分类型 匿名方法 迭代器 可空类型 Getter / setter单独可访问性 方法组转换(代表) Co- and Contra-variance for delegates 静态 ...

  4. C# 9.0 新特性预览 - 类型推导的 new

    C# 9.0 新特性预览 - 类型推导的 new 前言 随着 .NET 5 发布日期的日益临近,其对应的 C# 新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章将向大 ...

  5. C# 7.0 新特性2: 本地方法

    本文参考Roslyn项目中的Issue:#259. 1. C# 7.0 新特性1: 基于Tuple的“多”返回值方法 2. C# 7.0 新特性2: 本地方法 3. C# 7.0 新特性3: 模式匹配 ...

  6. C# 7.0 新特性4: 返回引用

    本文参考Roslyn项目中的Issue:#118. 1. C# 7.0 新特性1: 基于Tuple的“多”返回值方法 2. C# 7.0 新特性2: 本地方法 3. C# 7.0 新特性3: 模式匹配 ...

  7. [转]Servlet 3.0 新特性详解

    原文地址:http://blog.csdn.net/xiazdong/article/details/7208316 Servlet 3.0 新特性概览 1.Servlet.Filter.Listen ...

  8. 【servlet3.0新特性】Annotation注解配置

    servlet3.0新特性Servlet3.0引入的若干重要新特性,包括异步处理.新增的注解支持.可插性支持等等,为读者顺利向新版本过渡扫清障碍.Servlet3.0新特性概述Servlet3.0作为 ...

  9. ASP.NET Web API 2.0新特性:Attribute Routing1

    ASP.NET Web API 2.0新特性:Attribute Routing[上篇] 对于一个针对ASP.NET Web API的调用请求来说,请求的URL和对应的HTTP方法的组合最终决定了目标 ...

随机推荐

  1. XXX_ProductCRUD的项目结构与配置文件

    MVC_ProductCRUD                                                       Hibernate_ProductCRUD 项目结构    ...

  2. Linux 番茄时钟 定时 取消 快捷方式

    shell 脚本 clock.sh #!/bin/bash if [ $1 == 0 ] then at -d `atq | awk -v ORS=" " '{a[NR]=$1} ...

  3. Android调试非常有用的命令集1_adb&aapt&git&repo&scp&while

    Linux部分场景非常有用的命令集_1_持续更新 这里面也包含了对于开发调试有用的命令,也可以看看. 这里不做详细说明或截图,仅作为记录和简单说明.注:可能只针对某一命令部分功能,不包含整个功能,若要 ...

  4. 【C++】C++数据类型

    注意:以下内容摘自文献[1],修改了部分内容. 计算机处理的对象是数据,而数据是以某种特定的形式存在的(例如整数.浮点数.字符等形式).数据结构指的是数据的组织形式.例如,数组就是一种数据结构. 1. ...

  5. SpringBoot—自定义线程池及并发定时任务模板

    介绍   在项目开发中,经常遇到定时任务,今天通过自定义多线程池总结一下SpringBoot默认实现的定时任务机制. 定时任务模板 pom依赖 <dependencies> <dep ...

  6. 使用Redis分布式锁实现主备

    使用Redis分布式锁实现集群的主备 最近工作中遇到一个问题,我们会调用业务部门提供的HTTP接口获取所有的音视频任务信息,这些任务会被分发到各个机器节点进行处理.有两个方案: 方案一 为每台机器编号 ...

  7. Black Hat Python之#2:TCP代理

    在本科做毕设的时候就接触到TCP代理这东西,当时需要使用代理来对发送和收到的数据做修改,同时使用代理也让我对HTTP协议有了更深的了解. TCP Proxy用到的一个主要的东西就是socket.pro ...

  8. N3飞控踩坑指南

    1.想要使用上位机仿真的话,在本次连接上位机的过程中不要点击IMU校准. 2.两路12S电池并联为飞控供电时(DJI智能电池),需要确保所有电池均为满电.否则如果上电时电量不平衡,电池之间将会自动互相 ...

  9. 使用PRTG和panabit结合定位网络阻塞的来源

    一.背景   在网络管理工作中,有时会出现网络阻塞,需要定位阻塞来源以采取措施解决问题.二.以一个网络阻塞案例说明定位方法   案例:某企业日常使用多条网络线路,某一段时间发现某条线路传输速率下降,对 ...

  10. URL与URI的联系与区别

    作者:daixinye链接:https://www.zhihu.com/question/21950864/answer/154309494来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商 ...