模式匹配(Pattern Matching)是一种强大的特性,允许以简洁的方式检查和处理数据的类型、值或结构。相比传统的 if
语句,模式匹配可以让代码更简洁、可读性更高,尤其是在处理复杂条件或类型检查时。本文对 C# 模式匹配与 if
语句的对比和说明,重点介绍模式匹配的用法和优势。
模式匹配简介
C# 从 7.0 版本开始引入模式匹配,并随着版本迭代(如 8.0、9.0)不断增强。它主要用于:
- • 检查对象的类型(类型模式)。
- • 匹配常量或值(常量模式)。
- • 检查对象的属性或结构(属性模式、递归模式等)。
- • 简化条件逻辑,替代冗长的
if-else
结构。
主要场景:
- •
is
运算符 - •
switch
语句/表达式 - •
when
子句结合模式匹配 - • 解构(Deconstruction)和元组
常见形式
is
模式匹配
is
运算符用于检查类型并可直接声明变量
object value = 42;
if (value is int number)
{
Console.WriteLine($"It's an integer: {number}");
}
- • 优势:无需显式类型转换(如
(int)value
)。 - • 适用场景:简单类型检查、类型转换。
switch
语句中的模式匹配
C# 7.0 引入了增强的 switch
语句,支持类型模式和 when
子句:
object obj = 42;
switch (obj)
{
caseint i when i > 0:
Console.WriteLine("Positive integer");
break;
caseint i when i <= 0:
Console.WriteLine("Non-positive integer");
break;
casestring s:
Console.WriteLine($"String: {s}");
break;
casenull:
Console.WriteLine("Null value");
break;
default:
Console.WriteLine("Unknown type");
break;
}
- • 优势:可以根据类型、值或条件进行分支处理,逻辑更清晰。
- • 适用场景:需要根据类型或条件执行不同逻辑。
switch
表达式(C# 8.0+)
switch
表达式是模式匹配的更简洁形式,返回值直接赋值:
object obj = "Hello";
string result = obj switch
{
int i => $"Integer: {i}",
string s when s.Length > 3 => $"Long string: {s}",
string s => $"Short string: {s}",
_ => "Unknown"
};
Console.WriteLine(result); // 输出:Long string: Hello
- • 优势:更简洁,适合返回值场景。
- • 适用场景:替代多分支
if-else
或简单的switch
语句。
属性模式(Property Pattern, C# 8.0+)
属性模式允许检查对象的属性值:
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}
Person person = new Person { Name = "Alice", Age = 25 };
if (person is { Age: >= 18 })
{
Console.WriteLine($"{person.Name} is an adult.");
}
- • 优势:直接匹配对象的属性,减少嵌套
if
语句。 - • 适用场景:需要检查对象属性的复杂条件。
元组和解构模式
模式匹配支持元组和解构,简化多值比较:
(int x, int y) point = (3, 4);
string location = point switch
{
(0, 0) => "Origin",
(var x, var y) when x > 0 && y > 0 => "First quadrant",
_ => "Other"
};
Console.WriteLine(location); // 输出:First quadrant
- • 优势:直接解构并匹配元组中的值。
- • 适用场景:处理元组或多值数据。
模式匹配 vs. if
语句的优缺点
模式匹配的优点
- 简洁性:减少类型转换和冗余代码。
- 可读性:逻辑更清晰,尤其是处理复杂类型或条件时。
- 表达力:支持复杂模式(如属性模式、递归模式)。
- 类型安全:编译器确保类型检查和转换的安全性。
模式匹配的局限性
- 学习曲线:对于新手,模式匹配的语法可能稍复杂。
- 适用范围:在简单条件判断中,
if
语句可能更直观。
- 适用范围:在简单条件判断中,
- 性能:模式匹配通常与
if
性能相当,但在复杂场景下需注意编译器优化。
- 性能:模式匹配通常与
if 语句的优点
- 简单直观:适合简单逻辑或不涉及类型检查的场景。
- 灵活性:可以处理任意复杂条件,不局限于模式匹配支持的结构。
- 熟悉度:开发人员通常更熟悉
if
语句。
- 熟悉度:开发人员通常更熟悉
if 语句的局限性
- 冗长:类型检查和转换需要更多代码。
- 可读性:嵌套
if
可能导致代码难以维护。
- 可读性:嵌套
- 错误风险:手动类型转换可能引发运行时异常。
模式匹配与 if
的综合对比的示例
使用 if
语句
public void ProcessShape(object shape)
{
if (shape is Circle)
{
var circle = (Circle)shape;
if (circle.Radius > 0)
{
Console.WriteLine($"Circle with radius {circle.Radius}");
}
}
elseif (shape is Rectangle)
{
var rect = (Rectangle)shape;
if (rect.Width > 0 && rect.Height > 0)
{
Console.WriteLine($"Rectangle with area {rect.Width * rect.Height}");
}
}
else
{
Console.WriteLine("Unknown shape");
}
}
使用模式匹配
public void ProcessShape(object shape)
{
switch (shape)
{
case Circle { Radius: > 0 } c:
Console.WriteLine($"Circle with radius {c.Radius}");
break;
case Rectangle { Width: > 0, Height: > 0 } r:
Console.WriteLine($"Rectangle with area {r.Width * r.Height}");
break;
default:
Console.WriteLine("Unknown shape");
break;
}
}