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


猜你喜欢
- mybatis oracle 自增序列的代码如下所示:<insert id=" insert " useGener
- 1. 为什么要进行参数校验在后端进行工作时,需要接收前端传来的数据去数据库查询,但是如果有些数据过于离谱,我们就可以直接把它pass掉,不让
- 代码如下一、创建CheckCode.xaml代码如下<ResourceDictionary xmlns="http
- 近期在开发中遇到一种需求:根据用户的权限决定是否显示某操作按钮。例如:若用户拥有删除数据的权限,则在界面中显示“删除”按钮;若用户无该权限,
- 以前我们说过在一些简单的例子中,比如为一个字段赋值或递增该字段,我们需要对线程进行同步,虽然lock可以满足我们的需要,但是一个竞争锁一定会
- gateway网关与前端请求的跨域问题最近因项目需要,引入了gateway网关。可是发现将前端请求的端口指向网关后,用postman发送请求
- Android Studio 打包 jar 及 aar 包创建工程 New -> Module -> Library在gradl
- 前言如何下载和使用MyBatis Generator 插件,只说代码,不讲感情。如果有问题还请多多指点。开发环境开发工具:IntelliJ
- 一. Window 分类应用 Window(ApplicationWindow: 对应一个 Acitivity)
- 引言二分查找底层依赖的是数组随机访问的特性,所以只能用数组来实现。如果数据存储在链表中,就真的没法用二分查找算法了吗?实际上,只需要对链表稍
- 本文实例讲述了Android使用ActionBar和ViewPager切换页面,分享给大家供大家参考。具体如下:运行效果截图如下:项目布局如
- SpringMVC文件上传中要解决的问题一、中文文件名编码问题通过过滤器解决二、文件位置存储问题放在当前项目下,作为静态资源,这样可以通过U
- SpringBoot控制配置类加载顺序@Configuration配置被加载进容器的方式大体上可分为3种手动:构建ApplicationCo
- 一、题目描述题目实现:在进行网络编程时,由于进行网络连接是比较消耗资源的,因此,可以对连接的等待时间进行设置,如果在规定的时间没有进行连接,
- 本文实例讲述了C#访问SqlServer设置链接超时的方法。分享给大家供大家参考。具体实现方法如下:下面这段代码设置超时时间为60秒,默认为
- 本文实例为大家分享了unity利用图片来生成字体的具体代码,供大家参考,具体内容如下开发中,可能会用到需要将图片转换成字体的需求。BMFON
- 目录1、在java中,无论在何处调用,使用静态属性必须以类名做前缀。2、若有定义语句: int a=10 ; double b=3.14 ;
- 最近研究C#相关的ORC技术,图像识别一般C和C++这种底层语言做的比较多,C#主要是依托一些封装好的组件进行调用,这里介绍三种身份证识别的
- 1、redis的几种常见客户端:Jedis:是Redis的Java实现客户端,提供了比较全面的Redis命令的支持;Redisson:实现了
- 1 前言ATMS 即 ActivityTaskManagerService,用于管理 Activity 及其容器(任务、堆栈、显示等)。AT