C# 8.0 模式匹配进阶:Switch 表达式与属性/位置模式详解
C# 8.0 引入了更为强大的模式匹配机制,核心在于 Switch 表达式以及衍生的 Property 和 Positional 模式。本文将对比传统 switch-case 语法,通过具体代码示例演示如何将这些新模式应用于对象类型判断、属性值提取及状态机处理中,帮助你掌握简化复杂逻辑的技巧。
从传统 Switch 到 Switch 表达式
在 C# 7.0 时代,模式匹配主要依赖 case Type variable when condition: 这种长格式写法。虽然在 C# 8.0 中传统写法依然可用,但新的 Switch 表达式提供了更函数式的表达方式。
以一个简单的 Point 类为例,我们先回顾 C# 7.0 的经典实现:
class Point
{
public int X { get; }
public int Y { get; }
public Point(int x, int y) => (X, Y) = (x, y);
public void Deconstruct(out int x, out int y) => (x, y) = (X, Y);
}
static string Display(object o)
{
switch (o)
{
case Point p when p.X == 0 && p.Y == 0:
return "origin";
case Point p:
return $"({p.X}, {p.Y})";
default:
return "unknown";
}
}
进入 C# 8.0 后,可以使用箭头操作符 => 将 switch 表达式写在一行或紧凑的多行结构中,语义同样连贯:
static string Display(object o) => o switch
{
Point p when p.X == 0 && p.Y == 0 => "origin",
Point p => $"({p.X}, {p.Y})",
_ => "unknown"
};
第1步:理解 Switch 表达式的构成
- 入口:对变量
o调用.switch方法(实际上是语言层面的模式匹配支持)。 - 动作:花括号内包含多组模式与对应的结果表达式,用逗号分隔。
- 参数:
_是弃元模式,代表通配符,用于捕获无法被前面模式匹配的情况。
Property Patterns(属性模式)
当需要针对对象的特定属性进行精确判断时,C# 8.0 提供了属性模式。它允许直接在模式内部指定属性名和期望的值,无需先绑定变量再通过 when 关键字做额外校验。
优化上述示例,直接使用属性模式:
static string Display(object o) => o switch
{
Point { X: 0, Y: 0 } => "origin",
Point p => $"({p.X}, {p.Y})",
_ => "unknown"
};
属性模式还支持解构(Deconstruction),即在模式中直接将属性值提取到局部变量中:
static string Display(object o) => o switch
{
Point { X: 0, Y: 0 } => "origin",
Point { X: var x, Y: var y } => $"({x}, {y})",
_ => "unknown"
};
完成状态:当传入的 o 是 Point 实例且属性符合指定条件时,直接返回对应结果;若不符合,则继续向下匹配。
Positional Patterns(位置模式)
如果类的定义中包含 Deconstruct 方法(如上面的 Point 类所示),则可以更进一步,使用位置模式。这种方式类似于解构赋值,按顺序匹配属性。
static string Display(object o) => o switch
{
Point(0, 0) => "origin",
Point(var x, var y) => $"({x}, {y})",
_ => "unknown"
};
对于已经知道确切类型的情况(即不涉及基类或多态转换),可以省略类型名称,直接写位置模式:
static string Display(Point o) => o switch
{
(0, 0) => "origin",
(var x, var y) => $"({x}, {y})"
};
第2步:应用 Tuple 模式进行状态流转判断
除了对象实例,Tuple 模式也非常适用于多条件的组合判断,例如状态机的状态切换:
static State ChangeState(State current, Transition transition, bool hasKey) =>
(current, transition, hasKey) switch
{
(Opened, Close, _) => Closed,
(Closed, Open, _) => Opened,
(Closed, Lock, true) => Locked,
(Locked, Unlock, true) => Closed,
_ => throw new InvalidOperationException("Invalid transition")
};
在此场景中,_ 用作占位符忽略第三个参数(如钥匙状态)在不相关路径下的影响,极大地提升了可读性。
简化的非空判断
在实际业务中,经常会遇到“判空”的需求。在传统写法中,我们通常习惯先写 if (obj is null)。在 C# 8.0 中,这可以用极短的模式文字完成:
{ } => o.ToString(), // 非空对象
null => "null" // 显式匹配 null
注意:{ } 表示匹配任何非空值的模式(Non-null pattern)。结合 Switch 表达式使用时,可以非常干净地处理可能为空的数据。
第3步:综合实战建议
- 入口:识别项目中大量的
if-else链或冗长的switch-case。 - 动作:优先检查对象类型是否明确,若是,尝试转换为 Switch 表达式。
- 参数:利用属性模式替换
when从句中的相等比较,让意图一目了然。
总结
C# 8.0 的模式匹配(Pattern Matching)不仅仅是语法糖,它从根本上改变了声明式数据的处理方式。通过 Switch 表达式、Property Patterns 和 Positional Patterns 的组合,开发者可以将复杂的分支逻辑扁平化,减少中间变量的声明,使代码意图更加直观。建议在涉及多类型分发、数据验证或简单状态流转的场景中优先采用这些新特性。
以上就是 C# 8.0 模式匹配新特性的详细内容,更多关于 C# 编程技巧的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













