前言
嗨,大家好!
我总结了模式匹配 10 个常用方法,我们继续一起深入挖掘 C# 模式匹配的魅力,看看它如何帮助我们编写更简洁、更易读且更具表现力的代码!
一些澄清
有的小伙伴以为有了模式匹配,就可以彻底抛弃 if-else
语句了。
其实不然,模式匹配本质上也是一种高级的条件判断方式,它提供了一种更灵活的方式来进行条件判断,特别是新的 switch
表达式语法,可以更灵活地控制逻辑,简化复杂逻辑的判断,编写出更具表现力和功能强大的代码。
基本语法
1. 使用 is 关键字进行类型模式匹配
if (obj is string str)
{
Console.WriteLine($"String length is: {str.Length}");
}
2. 在 switch 语句中使用模式匹配
从 C# 8.0 开始,switch
语句被增强为 switch
表达式,允许更简洁的语法(特别是结合 when
子句),并且可以直接返回值,可以替代传统的条件语句,提高代码的可读性和简洁性。
普通 switch
表达式:
var time = DateTime.Now;
switch (time)
{
case { Year: 2023 or 2024, Month: <= 12, Day: 12 } t:
Console.WriteLine($"the first day of every month in the first half of 2020 and 2021");
break;
}
在 switch
表达式中直接返回值的简洁写法:
string GetAnimalSound(Animal animal) => animal switch
{
Dog => "Woof!",
Cat => "Meow!",
_ => "Unknown sound"
};
10 常用的使用方法
1. 类型模式
检查一个表达式是否属于特定类型,并且可以选择性地将该表达式转换为该类型。
object obj = "Hello, World!";
if (obj is string str)
{
Console.WriteLine($"String length: {str.Length}");
}
2. 常量模式
检查一个表达式的值是否等于某个常量,这是最简单的模式匹配形式。
object value = 42;
switch (value)
{
case 42:
Console.WriteLine("The answer to life, the universe, and everything.");
break;
default:
Console.WriteLine("Just another number.");
break;
}
3. 属性模式
允许你根据对象的属性值进行匹配,这在处理复杂对象时非常有用
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
Person person = new() { Name = "Alice", Age = 30 };
switch (person)
{
case Person p when p.Age < 18:
Console.WriteLine($"{p.Name} is a minor.");
break;
case Person p when p.Age >= 18 && p.Age < 65:
Console.WriteLine($"{p.Name} is an adult.");
break;
case Person p when p.Age >= 65:
Console.WriteLine($"{p.Name} is a senior citizen.");
break;
}
4. 关系模式
使用关系运算符(如<
, >
)进行匹配
object value = 7;
if (value is int a && a > 6)
{
Console.WriteLine(a);
}
5. 逻辑模式
使用逻辑运算符(如and
, or
, not
)组合多个模式
object value = 7;
if (value is int a && a > 6 && a < 10)
{
Console.WriteLine(a);
}
6. 元组模式
允许你对元组中的元素进行解构和匹配
var point = (x: 10, y: 20);
switch (point)
{
case (0, 0):
Console.WriteLine("Origin");
break;
case (var x, 0):
Console.WriteLine($"On X-axis at ({x}, 0)");
break;
case (0, var y):
Console.WriteLine($"On Y-axis at (0, {y})");
break;
case (var x, var y):
Console.WriteLine($"Point at ({x}, {y})");
break;
}
7. 位置模式
位置模式可以对对象的属性进行检查和匹配
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
void CheckPerson(Person person)
{
switch (person)
{
case { Name: "Alice", Age: 30 }:
Console.WriteLine("Found Alice, Age 30");
break;
default:
// 如果有其他情况需要处理,可以在这里添加逻辑
break;
}
}
8. 递归模式
C# 8.0 引入了对更复杂对象结构的模式匹配,允许嵌套匹配。
public class Animal
{
public string Type { get; set; }
}
public class Dog : Animal
{
public string Breed { get; set; }
}
void CheckAnimal(Animal animal)
{
switch (animal)
{
case Dog { Breed: "Labrador" }:
Console.WriteLine("It's a Labrador!");
break;
}
}
9. 列表模式
列表模式允许将数组或列表与一系列模式进行匹配。
列表模式的语法是用方括号括起来的值。
例如:
int[] numbers = { 1, 2, 3 };
// 使用列表模式来匹配一个整数数组
Console.WriteLine(numbers is [1, 2, 3]); // True
事实上,列表模式可以使用任何模式,包括常量、类型、属性和关系模式。
例如:
List<int> numbers = new() { 1, 2, 3 };
// 使用弃元模式(_)和 var 模式来匹配数组中的元素
if (numbers is [var first, _, _])
{
Console.WriteLine($"列表中的第 1 个元素是 {first}。");
}
// 输出:
// 列表中的第 1 个元素是 1。
10. 切片模式
切片模式允许匹配零个或多个元素的序列。
切片模式的语法是两个点(…)。
例如,以下代码展示了如何使用切片模式来匹配数组中的元素:
void MatchMessage(string message)
{
var result = message is ['a' or 'A', .. var s, 'a' or 'A']
? $"Message {message} matches; inner part is {s}."
: $"Message {message} doesn't match.";
Console.WriteLine(result);
}
MatchMessage("aBBA"); // 输出: Message aBBA matches; inner part is BB.
MatchMessage("apron"); // 输出: Message apron doesn't match.
PS:可以利用切片模式的特点丢弃或捕获零个或多个元素。例如:
void List_Pattern(object[] num)
{
int a = 0;
// 匹配数组中的前三个元素,并将第三个元素赋值给变量third
if (num is [1, int, var third, _])
{
Console.WriteLine("第一个为整数1");
Console.WriteLine("第二个为整数类型");
Console.WriteLine($"第三个为{third.ToString()}");
Console.WriteLine("第四个随便");
}
}
总结
总而言之,C# 里的模式匹配功能强大且灵活,允许我们轻松地进行条件判断和数据解构,对于更复杂的数据结构和逻辑流程,模式匹配也提供了非常强大的支持,不妨在你的项目中应用起来,相信不会让你失望的!
好了,今天的分享就到这里啦,如果觉得有用,别忘了点个【赞与在看】哦,你的支持是我最大的动力!
最后,如果你有更好的想法或建议,欢迎留言讨论!
往期精彩
- 把 C# 里的 HttpClient 封装起来,告别复杂的配置,让 Restful API 调用更轻松更高效
- C#12 中 5 个节省你开发时间的的改进
- C# 静态类,高手不想让你知道的 15 个真相
- 封装一个 C# 范围判断函数,从此告别重复编写范围判断代码的烦恼
- 用 C# Stopwatch 计时,让代码性能飞起来!
- 轻装上阵,Visual Studio LocalDB:.NET 程序员的本地数据库神器
- 封装一个C#万能基础数据类型转换器,一招解决所有基础类型转换烦恼
- 闲话 .NET(7):.NET Core 能淘汰 .NET FrameWork 吗?
- 常用的 4 种 ORM 框架(EF Core,SqlSugar,FreeSql,Dapper)对比总结
- C# AutoMapper 10个常用方法总结
- C# 7个方法比较两个对象是否相等
- C# 去掉字符串最后一个字符的 4 种方法
我是老杨,一个执着于编程乐趣、至今奋斗在一线的 10年+ 资深研发老鸟,是软件项目管理师,也是快乐的程序猿,持续免费分享全栈实用编程技巧、项目管理经验和职场成长心得!欢迎点击下方卡片关注老杨的公众号(名称:代码掌控者),更多干货等你来!