C# 9.0 新特性之模式匹配简化
阅读本文大概需要 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 中,你可以通过逻辑操作符 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 还有很多其它好用的新特性,下一篇文章继续与你分享。文章写短一点不是因为我偷懒哈,而是为了促使大家一次性看完,方便大家在零碎时间阅读,避免因文章太长而成为“收藏不看”系列。
敬请关注我明天下一篇关于 C# 9.0 新特性的介绍,明天不见不散。
参考:
C# 9.0 新特性之模式匹配简化的更多相关文章
- C# 7.0 新特性3: 模式匹配
本文参考Roslyn项目Issue:#206,及Docs:#patterns. 1. C# 7.0 新特性1: 基于Tuple的“多”返回值方法 2. C# 7.0 新特性2: 本地方法 3. C# ...
- C# 7.0 新特性1: 基于Tuple的“多”返回值方法
本文基于Roslyn项目中的Issue:#347 展开讨论. 1. C# 7.0 新特性1: 基于Tuple的“多”返回值方法 2. C# 7.0 新特性2: 本地方法 3. C# 7.0 新特性3: ...
- C#7.0&6.0新特性 — 完整版
C#2.0 泛型 部分类型 匿名方法 迭代器 可空类型 Getter / setter单独可访问性 方法组转换(代表) Co- and Contra-variance for delegates 静态 ...
- C# 9.0 新特性预览 - 类型推导的 new
C# 9.0 新特性预览 - 类型推导的 new 前言 随着 .NET 5 发布日期的日益临近,其对应的 C# 新版本已确定为 C# 9.0,其中新增加的特性(或语法糖)也已基本锁定,本系列文章将向大 ...
- C# 7.0 新特性2: 本地方法
本文参考Roslyn项目中的Issue:#259. 1. C# 7.0 新特性1: 基于Tuple的“多”返回值方法 2. C# 7.0 新特性2: 本地方法 3. C# 7.0 新特性3: 模式匹配 ...
- C# 7.0 新特性4: 返回引用
本文参考Roslyn项目中的Issue:#118. 1. C# 7.0 新特性1: 基于Tuple的“多”返回值方法 2. C# 7.0 新特性2: 本地方法 3. C# 7.0 新特性3: 模式匹配 ...
- [转]Servlet 3.0 新特性详解
原文地址:http://blog.csdn.net/xiazdong/article/details/7208316 Servlet 3.0 新特性概览 1.Servlet.Filter.Listen ...
- 【servlet3.0新特性】Annotation注解配置
servlet3.0新特性Servlet3.0引入的若干重要新特性,包括异步处理.新增的注解支持.可插性支持等等,为读者顺利向新版本过渡扫清障碍.Servlet3.0新特性概述Servlet3.0作为 ...
- ASP.NET Web API 2.0新特性:Attribute Routing1
ASP.NET Web API 2.0新特性:Attribute Routing[上篇] 对于一个针对ASP.NET Web API的调用请求来说,请求的URL和对应的HTTP方法的组合最终决定了目标 ...
随机推荐
- 201771010117—马兴德—实验一 软件工程准备—掌握博客中MarkDown的使用以及通读《现代软件工程—构建之法》的总结
实验一 软件工程的前期准备工作 在前期的准备工作以及老师上课的讲解中,我懂得了"软件=程序+软件工程"这句话的基本含义,以前只是对软件工程有一个很浅显的概念,现在在读了<现代 ...
- RAC配置2个私网网卡使用HAIP服务
如果是在oracle 10gRAC, 私网网卡冗余保护只能使用操作系统网卡绑定方式,但是到了oracle 11g,如果担心一个私网网卡故障导致rac节点驱逐,可以使用2个私网网卡,Oracle将自动使 ...
- PHP设计模式(一)
1)工厂模式 工厂模式是用工厂方法生成对象,而不是直接new一个对象.假设我们在Config命名空间下有一个名叫Db的数据库操作类,用普通的方法,如果我们想去创建一个Db的对象,我们会直接new一个出 ...
- 转 vue动画总结
使用过渡类名(有进入及出去,适合显示隐藏,需要配合v-if) .v-enter,//进入前 .v-leave-to {//离开后 只需要入场动画 可以把v-leave-to删掉 opacity: 0; ...
- 利用pandas进行数据子集的获取
- 如何使用git命令行上传项目到github
第一步:我们需要先创建一个本地的版本库(其实也就是一个文件夹). 你可以直接右击新建文件夹,也可以右击打开Git bash命令行窗口通过命令来创建. 现在我通过命令行在桌面新建一个TEST文件夹(你也 ...
- 计算机启动 Ubuntu系统初始化 SysV Systemd
计算机启动过程 第一阶段:BIOS boot (bootstrap的缩写)来自一句谚语:"pull oneself up by one's bootstraps" 最早的时候,计算 ...
- Redis学习笔记(1)
一.NoSQL基础知识 1. NoSQL概念 NoSQL(NoSQL = Not Only SQL ),意即“不仅仅是SQL”,泛指非关系型的数据库.随着互联网web2.0网站的兴起,传统的关系数据库 ...
- MySQL/MariaDB随笔一
1.yum 安装后先跑一下系统自带的安全脚本,否则数据库很不安全,任何人都可以登录 [root@xixi ~]# mysql_secure_installation NOTE: RUNNING ALL ...
- [工具推荐]004.EXE签名工具SignTool使用教程
数字证书,真是个神奇的东西,可以保证软件不被修改,可以表明文件的发布日期,最重要的,可以很大程度的减少杀毒软件的误报,当然,这就要使用可信任的机构颁发的证书了. 现在要说的不是申请证书,而是如何制作自 ...