C# 7.0 新特性:模式匹配 ( pattern matching)
c# 特性 pattern 7.0 matching 模式匹配
2023-09-11 14:21:32 时间
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#中Linq查询条件动态化
- C#中缓存的使用 ajax请求基于restFul的WebApi(post、get、delete、put) 让 .NET 更方便的导入导出 Excel .net core api +swagger(一个简单的入门demo 使用codefirst+mysql) C# 位运算详解 c# 交错数组 c# 数组协变 C# 添加Excel表单控件(Form Controls) C#串口通信程序
- 详解C#泛型(二) 获取C#中方法的执行时间及其代码注入 详解C#泛型(一) 详解C#委托和事件(二) 详解C#特性和反射(四) 记一次.net core调用SOAP接口遇到的问题 C# WebRequest.Create 锚点“#”字符问题 根据内容来产生一个二维码
- [翻译] C# 8.0 新特性 Redis基本使用及百亿数据量中的使用技巧分享(附视频地址及观看指南) 【由浅至深】redis 实现发布订阅的几种方式 .NET Core开发者的福音之玩转Redis的又一傻瓜式神器推荐
- EF+LINQ事物处理 C# 使用NLog记录日志入门操作 ASP.NET MVC多语言 仿微软网站效果(转) 详解C#特性和反射(一) c# API接受图片文件以Base64格式上传图片 .NET读取json数据并绑定到对象
- 浅谈JS中的!=、== 、!==、===的用法和区别 JS中Null与Undefined的区别 读取XML文件 获取路径的方式 C#中Cookie,Session,Application的用法与区别? c#反射 抽象工厂
- C#学习记录——软件工程师必备素养与技能
- 【C#】范型详解
- 【代码笔记】c# Linq操作DataTable
- C#【高级篇】StructLayout特性是什么?怎么用?
- C#实现程序自重启
- C#实现查找指定端口被哪个进程占用并处理进程及dos命令下操作
- [C#] Direct2D 学习笔记 (一)vb.net转换为c#
- C# StructLayout特性
- C# Lambda表达式Contains方法 like
- C# 可变参数函数
- C#怎么给新建的winform程序添加资源文件夹Resources
- C# params关键字
- C# 数组转json