阅读本文大概需要 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. WARN: Establishing SSL connection without server’s identity verification is not recommended

    问题 使用Spring JDBC 连接 MySQL时,出现如下警告: WARN: Establishing SSL connection without server's identity verif ...

  2. python+selenium实现百度关键词搜索自动化操作

    缘起 之前公司找外面网络公司做某些业务相关关键词排名,了解了一下相关的情况,网络公司只需要我们提供网站地址和需要做的关键词即可,故猜想他们采取的方式应该是通过模拟用户搜索提升网站权重进而提升排名. 不 ...

  3. SQL——SQL约束

    SQL约束 - 用于限制加入表的数据的类型    可以在创建表时规定约束(通过 CREATE TABLE 语句),或者在表创建之后也可以(通过 ALTER TABLE 语句).    NOT NULL ...

  4. 使用盒子定位布局时margin和padding使用

    首先说的是区别: 如图所示,黄色padding,绿色margin,中间的content是内容,margin和padding的值是不计算在内容高宽的.这里补充的是在实际情况中边框宽度也是不计算在内的.这 ...

  5. iOS开发图片选择

    一行代码搞定图片选择 // // gzhPhotoManager.h // 图片选择 // // Created by 郭志贺 on 2020/5/26. // Copyright © 2020 郭志 ...

  6. 了解Lombok插件

    Lombok是什么 Lombok可以通过注解形式帮助开发人员解决POJO冗长问题,帮助构造简洁和规范的代码,通过注解可产生相应的方法. Lombok如何在IDEA中使用 我们都知道,使用一种工具,一定 ...

  7. CSS基础选择器总结

    基础选择器 作用 特点 使用情况 用法 标签选择器 可以选出所有相同的标签,比如p 不能差异化选择 较多 p {color:red;} 类选择器 可以选出1个或多个标签 可以根据需求选择 非常多 .n ...

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

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

  9. ES6-面向对象即类

    简单介绍 在ES6面向对象基本上与java的类实现类似 1 class关键字,构造器和类分开了 1.1 ES5代码如下 <!DOCTYPE html> <html lang=&quo ...

  10. jchdl - GSL实例 - MulC2(有符号数的乘法)

      这里的实现,先把符号位取出来,使用两个正数相乘,然后在把符号加到乘积上.   参考链接 https://github.com/wjcdx/jchdl/blob/master/src/org/jch ...