C# 8.0 模式匹配进阶:Switch 表达式与属性/位置模式详解

晚来风
晚来风
发布时间:2026-10-15| 4人浏览过
原创

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# 编程技巧的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。