告别 if-else:C#.NET 模式匹配让代码更优雅的正确方式

简介

模式匹配是 C# 7.0 开始引入的革命性特性,它提供了更简洁、更强大的方式来检查和提取数据中的信息。随着每个版本的更新,模式匹配功能不断强化,成为现代 C# 开发的核心特性。

模式匹配允许将输入表达式与各种特征进行匹配,支持多种模式类型。它主要用于:

  • is 表达式:检查并可能声明变量。

  • switch 语句:传统分支逻辑。

  • switch 表达式:更简洁的表达式形式(C# 8.0 引入)。

模式匹配演进历程

版本 新增特性
C# 7.0 基本模式匹配:is 表达式、switch 语句增强
C# 8.0 递归模式、属性模式、位置模式、switch 表达式
C# 9.0 类型模式简化、逻辑模式(and/or/not)、关系模式
C# 10.0 扩展属性模式
C# 11.0 列表模式、切片模式

基础模式类型

声明模式

csharp 复制代码
// 检查类型并声明新变量
if (obj is string str)
{
    Console.WriteLine($"字符串长度: {str.Length}");
}

// 传统方式对比
if (obj is string)
{
    string str = (string)obj;
    Console.WriteLine($"字符串长度: {str.Length}");
}

类型模式

csharp 复制代码
// 只检查类型,不声明变量
if (obj is string)
{
    Console.WriteLine("这是一个字符串");
}

// 在 switch 表达式中使用
var result = obj switch
{
    string => "它是字符串",
    int => "它是整数",
    _ => "其他类型"
};

常量模式

csharp 复制代码
// 检查特定值
if (value is 5) { /* 值等于5 */ }
if (value is null) { /* 值为null */ }
if (value is "hello") { /* 字符串比较 */ }

// 在 switch 中
string message = value switch
{
    0 => "零",
    1 => "一",
    null => "空值",
    _ => "其他值"
};

高级模式匹配

属性模式

csharp 复制代码
// 检查对象属性
if (person is { Name: "John", Age: > 18 })
{
    Console.WriteLine("John 已成年");
}

// 嵌套属性模式
if (order is { Customer: { Address: { City: "Beijing" } } })
{
    Console.WriteLine("北京客户的订单");
}

// C# 10 扩展属性模式
if (order is { Customer.Address.City: "Beijing" })
{
    Console.WriteLine("北京客户的订单(简化写法)");
}

位置模式(元组模式)

csharp 复制代码
// 元组解构和匹配
var point = (x: 5, y: 10);
var quadrant = point switch
{
    (0, 0) => "原点",
    (var x, var y) when x > 0 && y > 0 => "第一象限",
    (var x, var y) when x < 0 && y > 0 => "第二象限",
    (var x, var y) when x < 0 && y < 0 => "第三象限",
    (var x, var y) when x > 0 && y < 0 => "第四象限",
    _ => "在坐标轴上"
};

逻辑模式(C# 9.0+)

csharp 复制代码
// 使用逻辑运算符组合模式
bool IsValid(object obj) => obj is not null and (string or int);

// 复杂逻辑组合
var category = value switch
{
    > 0 and < 10 => "小的正数",
    < 0 or > 100 => "超出范围",
    not null => "非空值",
    _ => "其他"
};

关系模式(C# 9.0+)

csharp 复制代码
// 使用关系运算符
string GetSize(int value) => value switch
{
    < 0 => "负数",
    >= 0 and < 10 => "小",
    >= 10 and < 100 => "中",
    >= 100 => "大"
};

// 与类型模式结合
string Describe(object obj) => obj switch
{
    int i when i < 0 => "负整数",
    int i when i > 0 => "正整数",
    int => "零",
    _ => "其他"
};

列表模式(C# 11.0+)

csharp 复制代码
// 匹配数组或列表的特定模式
int[] numbers = { 1, 2, 3, 4 };

var result = numbers switch
{
    [1, 2, 3, 4] => "精确匹配",
    [1, 2, ..] => "以1,2开头",
    [.., 3, 4] => "以3,4结尾",
    [1, .. var middle, 4] => $"以1开头4结尾,中间有{middle.Length}个元素",
    [] => "空数组",
    _ => "其他模式"
};

// 切片模式
if (numbers is [var first, .. var rest])
{
    Console.WriteLine($"第一个元素: {first}, 剩余元素: {rest.Length}");
}

字符串模式

csharp 复制代码
string text = "Hello, World";

if (text is ['H','e','l','l','o', ..])
{
    Console.WriteLine("以Hello开头");
}

// 与Span<char>模式匹配结合
ReadOnlySpan<char> span = text.AsSpan();
if (span is ['H','e','l','l','o', ..])
{
    Console.WriteLine("匹配Span");
}

自定义模式匹配

csharp 复制代码
// 通过 Deconstruct 方法支持位置模式
public class Point
{
    public int X { get; }
    public int Y { get; }
    
    public void Deconstruct(out int x, out int y)
    {
        x = X;
        y = Y;
    }
}

// 现在可以对 Point 使用位置模式
var quadrant = point switch
{
    (0, 0) => "原点",
    (var x, var y) when x > 0 && y > 0 => "第一象限",
    // ...
};w

表达式树中的模式匹配

csharp 复制代码
Expression<Func<object, bool>> expr = o => o switch
{
    int i when i > 0 => true,
    string s when s.Length > 5 => true,
    _ => false
};

// 解析表达式树
if (expr.Body is SwitchExpression switchExpr)
{
    foreach (SwitchCase @case in switchExpr.Cases)
    {
        // 处理每个case
    }
}

实际应用场景

数据验证和处理

csharp 复制代码
public ValidationResult Validate(Order order)
{
    return order switch
    {
        null => ValidationResult.Failure("订单不能为空"),
        { TotalAmount: <= 0 } => ValidationResult.Failure("金额必须大于0"),
        { Customer: null } => ValidationResult.Failure("客户信息缺失"),
        { Items: [] } => ValidationResult.Failure("订单项不能为空"),
        { Status: OrderStatus.Cancelled } => ValidationResult.Failure("订单已取消"),
        _ => ValidationResult.Success()
    };
}

API 响应处理

csharp 复制代码
public string HandleResponse(ApiResponse response)
{
    return response switch
    {
        { StatusCode: 200, Data: not null } => "成功",
        { StatusCode: 404 } => "资源未找到",
        { StatusCode: >= 400 and < 500 } => "客户端错误",
        { StatusCode: >= 500 } => "服务器错误",
        { Error: not null } => $"错误: {response.Error.Message}",
        _ => "未知响应"
    };
}
相关推荐
绿荫阿广9 小时前
使用.NET开发并上线一个小智AI对话机器人的MCP服务转接平台
.net·asp.net core·mcp
Eiceblue10 小时前
通过 C# 将 HTML 转换为 RTF 富文本格式
开发语言·c#·html
IUGEI11 小时前
synchronized的工作机制是怎样的?深入解析synchronized底层原理
java·开发语言·后端·c#
棉晗榜12 小时前
无法解析位于...\global.json 的 global.json 中指定的 .NET SDK 版本
.net
czhc114007566313 小时前
C# 1124 接收
开发语言·c#
时光追逐者15 小时前
C#/.NET/.NET Core技术前沿周刊 | 第 62 期(2025年11.17-11.23)
c#·.net·.netcore
司铭鸿15 小时前
祖先关系的数学重构:从家谱到算法的思维跃迁
开发语言·数据结构·人工智能·算法·重构·c#·哈希算法
宝桥南山18 小时前
.NET 10 - Blazor web assembly应用的一些诊断方式
microsoft·微软·c#·asp.net·.net·.netcore
sz老兄闯18 小时前
对 .NET FileSystemWatcher引发内存碎片化的 反思
.net