C# 7.0 新特性:模式匹配 ( pattern matching)
C# 7.0 新特性:模式匹配 ( pattern matching )
在 C# 中,is 是一个关键字,可以用来检查某个数据的类型是否为特定类型。这是一个表达式,返回类型为 boolean。
例如,我们可以检查某个实例是否为 Persion 类型
if (obj is Person) {
// Do something if obj is a Person.
}
在下面情况下,返回 true:
- 表达式的类型与 is 类型相符
- 表达式的类型为 is 类型的派生类型
- 表达式具有一个编译时类型, 它是 is 类型的基类,在运行时的值为 is 类型的派生类型
- 表达式实现了 is 类型的接口
支持模式匹配的 is
类型模式
在 C# 7.0 中,is 在原来的基础上,额外提供了类型转换的支持。可以在类型检查的基础上,直接支持类型转换。
在下面的示例中,我们希望检查对象的类型,如果为指定类型,我们要转型为特定的类型进行操作。
using System; public class Example
{
public static void Main()
{
Object o = new Person("Jane");
ShowValue(o); o = new Dog("Alaskan Malamute");
ShowValue(o);
} public static void ShowValue(object o)
{
if (o is Person p) {
Console.WriteLine(p.Name);
}
else if (o is Dog d) {
Console.WriteLine(d.Breed);
}
}
} public struct Person
{
public string Name { get; set; } public Person(string name) : this()
{
Name = name;
}
} public struct Dog
{
public string Breed { get; set; } public Dog(string breedName) : this()
{
Breed = breedName;
}
}
// The example displays the following output:
// Jane
// Alaskan Malamute
等价的以前代码为:
if (o is Person) {
Person p = (Person) o;
Console.WriteLine(p.Name);
}
else if (o is Dog) {
Dog d = (Dog) o;
Console.WriteLine(d.Breed);
}
常量匹配
is 后面还可以是常量,is 测试表达式的值是否为特定常量。在以前版本中,这需要使用 switch 来支持。
using System; public class Dice
{
Random rnd = new Random();
public Dice()
{ }
public int Roll()
{
return rnd.Next(1, 7);
}
} class Program
{
static void Main(string[] args)
{
var d1 = new Dice();
ShowValue(d1);
} private static void ShowValue(object o)
{
const int HIGH_ROLL = 6; if (o is Dice d && d.Roll() is HIGH_ROLL)
Console.WriteLine($"The value is {HIGH_ROLL}!");
else
Console.WriteLine($"The dice roll is not a {HIGH_ROLL}!");
}
}
// The example displays output like the following:
// The value is 6!
var 匹配
如果 is 后面是 var,则永远为 true 。并把值赋予后面的变量。
例如,下面代码将 item 赋予了 obj。
if (item is var obj)
需要注意的是,即使被测试的值为 null,is 表达式还是为 true。此时,变量将被赋予 null。
支持模式匹配的 Switch
所有的 c# 版本都支持常量模式,在 C# 7.0 中,现在支持类型模式了。也就是说,在 case 后面还可以是一个用来检测的类型。
case type varname
相当于在这里使用了 is 。
从 C# 7.0 开始,您还可以在上面的表达式后面附加一个返回 boolean 的 when 条件,以进一步检查。使用它的常见场景就是当值为 null 时。
using System; public abstract class Shape
{
public abstract double Area { get; }
public abstract double Circumference { get; }
} public class Rectangle : Shape
{
public Rectangle(double length, double width)
{
Length = length;
Width = width;
} public double Length { get; set; }
public double Width { get; set; } public override double Area
{
get { return Math.Round(Length * Width,2); }
} public override double Circumference
{
get { return (Length + Width) * 2; }
}
} public class Square : Rectangle
{
public Square(double side) : base(side, side)
{
Side = side;
} public double Side { get; set; }
} public class Circle : Shape
{
public Circle(double radius)
{
Radius = radius;
} public double Radius { get; set; } public override double Circumference
{
get { return 2 * Math.PI * Radius; }
} public override double Area
{
get { return Math.PI * Math.Pow(Radius, 2); }
}
} public class Example
{
public static void Main()
{
Shape sh = null;
Shape[] shapes = { new Square(10), new Rectangle(5, 7),
sh, new Square(0), new Rectangle(8, 8),
new Circle(3) };
foreach (var shape in shapes)
ShowShapeInfo(shape);
} private static void ShowShapeInfo(Shape sh)
{
switch (sh)
{
// Note that this code never evaluates to true.
case Shape shape when shape == null:
Console.WriteLine($"An uninitialized shape (shape == null)");
break;
case null:
Console.WriteLine($"An uninitialized shape");
break;
case Shape shape when sh.Area == 0:
Console.WriteLine($"The shape: {sh.GetType().Name} with no dimensions");
break;
case Square sq when sh.Area > 0:
Console.WriteLine("Information about square:");
Console.WriteLine($" Length of a side: {sq.Side}");
Console.WriteLine($" Area: {sq.Area}");
break;
case Rectangle r when r.Length == r.Width && r.Area > 0:
Console.WriteLine("Information about square rectangle:");
Console.WriteLine($" Length of a side: {r.Length}");
Console.WriteLine($" Area: {r.Area}");
break;
case Rectangle r when sh.Area > 0:
Console.WriteLine("Information about rectangle:");
Console.WriteLine($" Dimensions: {r.Length} x {r.Width}");
Console.WriteLine($" Area: {r.Area}");
break;
case Shape shape when sh != null:
Console.WriteLine($"A {sh.GetType().Name} shape");
break;
default:
Console.WriteLine($"The {nameof(sh)} variable does not represent a Shape.");
break;
}
}
}
// The example displays the following output:
// Information about square:
// Length of a side: 10
// Area: 100
// Information about rectangle:
// Dimensions: 5 x 7
// Area: 35
// An uninitialized shape
// The shape: Square with no dimensions
// Information about square rectangle:
// Length of a side: 8
// Area: 64
// A Circle shape
其它资源:
C# 7.0 新特性:模式匹配 ( pattern matching)的更多相关文章
- C# 9.0 新特性之模式匹配简化
阅读本文大概需要 2 分钟. 记得在 MS Build 2020 大会上,C# 语言开发项目经理 Mads Torgersen 宣称 C# 9.0 将会随着 .NET 5 在今年 11 月份正式发布. ...
- C# 7.0 新特性3: 模式匹配
本文参考Roslyn项目Issue:#206,及Docs:#patterns. 1. C# 7.0 新特性1: 基于Tuple的“多”返回值方法 2. C# 7.0 新特性2: 本地方法 3. C# ...
- C#6.0,C#7.0新特性
C#6.0新特性 Auto-Property enhancements(自动属性增强) Read-only auto-properties (真正的只读属性) Auto-Property Initia ...
- 背水一战 Windows 10 (43) - C# 7.0 新特性
[源码下载] 背水一战 Windows 10 (43) - C# 7.0 新特性 作者:webabcd 介绍背水一战 Windows 10 之 C# 7.0 新特性 介绍 C# 7.0 的新特性 示例 ...
- [翻译] C# 8.0 新特性 Redis基本使用及百亿数据量中的使用技巧分享(附视频地址及观看指南) 【由浅至深】redis 实现发布订阅的几种方式 .NET Core开发者的福音之玩转Redis的又一傻瓜式神器推荐
[翻译] C# 8.0 新特性 2018-11-13 17:04 by Rwing, 1179 阅读, 24 评论, 收藏, 编辑 原文: Building C# 8.0[译注:原文主标题如此,但内容 ...
- C# 9.0新特性
CandidateFeaturesForCSharp9 看到标题,是不是认为我把标题写错了?是的,C# 8.0还未正式发布,在官网它的最新版本还是Preview 5,通往C#9的漫长道路却已经开始.前 ...
- 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 新特性1: 基于Tuple的“多”返回值方法
本文基于Roslyn项目中的Issue:#347 展开讨论. 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: 模式匹配 ...
- ASP.NET Web API 2.0新特性:Attribute Routing1
ASP.NET Web API 2.0新特性:Attribute Routing[上篇] 对于一个针对ASP.NET Web API的调用请求来说,请求的URL和对应的HTTP方法的组合最终决定了目标 ...
随机推荐
- Android Systrace 基础知识 -- Why 60 fps ?
1.正文 今天来讲一下为何我们讲到流畅度,要首先说 60 帧. 我们先来理一下基本的概念: 60 fps 的意思是说,画面每秒更新 60 次 这 60 次更新,是要均匀更新的,不是说一会快,一会慢,那 ...
- 2021年9月国产数据库排行榜-墨天轮:达梦奋起直追紧逼OceanBase,openGauss反超PolarDB再升一位
2021年9月国产数据库排行榜已在墨天轮发布,本月参与排名的数据库总数达到了142个. 一.9月国产数据库流行度排行榜前15名 先来看看排行榜前五名,虽然PingCAP的TiDB分数本月下降31.82 ...
- ide 安装eval reset插件 Pycharm 永久破解
ide 安装eval reset插件 Pycharm 永久破解 1.安装eval reset的目的 Jetbrains家的产品有一个很良心的地方,他会允许你试用30天(这个数字写死在代码里了)以评估是 ...
- kotlin类与对象——>对象表达式与对象声明、内联类
1.对象表达式与对象声明 有时候,我们需要创建一个对某个类做了轻微改动的类的对象,而不用为之显式声明新的子类.Kotlin 用对象表达式和对象声明处理这种情况 2.对象表达式 要创建一个继承自某个(或 ...
- Kubernetes 集群中 Ingress 故障的根因诊断
作者:scwang18,主要负责技术架构,在容器云方向颇有研究. 前言 KubeSphere 是青云开源的基于 Kubernetes 的云原生分布式操作系统,提供了比较炫酷的 Kubernetes 集 ...
- 实践出真知,小程序wepy,uni-app框架开发使用!
一.前提 目前我只使用过wepy和uni-app框架开发过小程序,着重比较这两个框架使用感受! 另外wepy框架已经不维护了,希望uni-app好好维护下去! wepy和uni-app都是类似于vue ...
- ABC372 (D,E)
ABC372 (D,E) D 一道比较简单的二分查找题目. 观察到每个数能成为 \(j\) 的条件是独立的,因此想到统计每个数能成为它前面哪些数的 \(j\). 对于每个\(ed\), 二分 \(1 ...
- games101_Homework5
使用光线追踪来渲染图像,实现两个部分:光线的生成和光线与三角的求交 你需要修改的函数是: • Renderer.cpp 中的 Render():这里你需要为每个像素生成一条对应的光 线,然后调用函数 ...
- Spring AI 再更新:如何借助全局参数实现智能数据库操作与个性化待办管理
引言 好的,今天我们继续聊一下Spring AI的相关内容.在10月的时候,我使用Spring AI搭建了一个简易版的个人助理系统,整体来说效果还是非常不错的.通过这次尝试,我对业务系统与AI结合的探 ...
- 干货分享:Air700ECQ的硬件设计,第一部分
一.绪论 Air700ECQ是一款基于移芯EC716E平台设计的LTE Cat 1无线通信模组.支持移动双模FDD-LTE/TDD-LTE的4G远距离无线传输技术.以极小封装,极高性价比,满足Io ...