C# 列表模式(List Patterns)深度解析:模式匹配再进化!

简介

列表模式是一种模式匹配机制,允许检查一个集合(例如数组、List<T>、或任何实现了 IEnumerable<T> 的类型)的元素数量、顺序以及每个元素的内容。

C# 10 之前,模式匹配 (Pattern Matching) 已支持 switch 表达式、类型模式、属性模式等,但对列表或序列的匹配还不够直观。 C# 11 引入 列表模式(List Patterns),让开发者可以:

  • 按顺序匹配数组、Span<T>IList<T> 等列表。

  • 检查长度、特定元素,甚至解构其中的值。

  • 结合 switch、is、when 等模式匹配写出简洁、声明式的代码。

✅ 列表模式是模式匹配的扩展,不是新的集合类型。

语法

列表模式使用方括号 [] 来定义要匹配的模式:

基本形式:

csharp 复制代码
[ element-pattern-1, element-pattern-2, ... ]
csharp 复制代码
// 检查列表是否恰好包含三个元素:1, 2, 3
if (list is [1, 2, 3])
{
    Console.WriteLine("列表包含精确序列 1, 2, 3");
}

元素模式可以是:

  • 常量(1、"abc")

  • 变量(var x)

  • 类型模式(int x)

  • 通配符(_)

  • 切片模式(..,C# 11 引入)

  • 嵌套模式({}、[] 等)

可以用于:

  • is 表达式

  • switch 表达式或语句

  • when 条件

匹配规则

  • 匹配顺序严格一致。

  • 元素数量需满足模式要求(可用切片模式放宽)。

  • 支持 IEnumerable、数组、Span<T>IList<T> 等实现 Length/Count 属性 + 索引器 的类型。

基础示例

精确匹配

csharp 复制代码
int[] numbers = { 1, 2, 3 };

if (numbers is [1, 2, 3])
    Console.WriteLine("Exact match!");

只有当数组是 {1,2,3} 且长度为 3 时才匹配。

通配符 _

csharp 复制代码
if (numbers is [1, _, 3])
    Console.WriteLine("Middle element can be anything");

忽略第二个元素,只要求首尾固定。

切片模式 ..

  • 匹配以 1 开头的任意长度数组。
csharp 复制代码
if (numbers is [1, ..])
    Console.WriteLine("Starts with 1");
  • 匹配以 3 结尾的数组。
csharp 复制代码
if (numbers is [.., 3])
    Console.WriteLine("Ends with 3");
  • 开头和结尾都可检查,中间元素数量不限。
csharp 复制代码
if (numbers is [1, .., 3])
    Console.WriteLine("Starts with 1 and ends with 3");

变量绑定

csharp 复制代码
if (numbers is [1, .. var middle, 3])
    Console.WriteLine($"Middle elements count: {middle.Length}");

使用 var middle 捕获中间切片。

类型模式

csharp 复制代码
object[] items = { "hello", 42, 99 };

if (items is ["hello", int x, ..])
    Console.WriteLine($"Second element is int: {x}");

结合类型模式和切片。

空集合匹配

csharp 复制代码
   if (arr is []) 
   {
       Console.WriteLine("Array is empty");
   }

嵌套列表模式

csharp 复制代码
object[] data = [1, [2, 3], 4];

string result = data switch
{
    [1, [2, 3], 4] => "Nested match: [1, [2, 3], 4]",
    _ => "No match"
};

Console.WriteLine(result); // 输出: Nested match: [1, [2, 3], 4]

结合 switch 表达式

csharp 复制代码
int[] nums = { 1, 2, 3, 4 };

string result = nums switch
{
    [1, 2, 3, 4] => "Exact 1-2-3-4",
    [1, ..]      => "Starts with 1",
    [.., 4]      => "Ends with 4",
    []           => "Empty list",
    _            => "Other"
};
Console.WriteLine(result);

高级示例

斐波那契检测

csharp 复制代码
int[] fib = { 0, 1, 1, 2, 3, 5, 8 };

if (fib is [0, 1, .. var rest])
    Console.WriteLine($"Fibonacci sequence with {rest.Length + 2} elements");

解析命令行参数

csharp 复制代码
string[] args = { "add", "user", "Alice" };

var command = args switch
{
    ["add", "user", var name] => $"Add user {name}",
    ["remove", "user", var name] => $"Remove user {name}",
    [] => "No command",
    _ => "Invalid"
};

Console.WriteLine(command);

带 when 条件

csharp 复制代码
if (numbers is [var first, .., var last] && first < last)
    Console.WriteLine($"First < Last ({first} < {last})");

适用场景

  • 数据验证:检查输入的集合是否符合预期结构。

  • 数据提取:从集合中提取特定元素到变量,减少手动索引操作。

  • 简化控制流:替代复杂的 if-else 或循环逻辑。

  • 递归处理:结合切片模式处理嵌套或不定长集合。

相关推荐
m5655bj16 小时前
通过 C# 将 RTF 文档转换为图片
开发语言·c#
MM_MS17 小时前
WinForm+C#小案例--->写一个记事本程序
开发语言·计算机视觉·c#·visual studio
步步为营DotNet19 小时前
深入理解IAsyncEnumerable:.NET中的异步迭代利器
服务器·前端·.net
浪客川19 小时前
高效日志分离器:一键筛选关键信息
开发语言·windows·c#
小熊熊知识库20 小时前
C# EF.core 介绍以及高性能使用
开发语言·c#
雨疏风骤124020 小时前
【FreeRTOS】任务、任务状态
开发语言·stm32·c#·rtos
️公子1 天前
传奇游戏集成系统
游戏·c#
玩泥巴的1 天前
强的飞起的 Roslyn 编译时代码生成,实现抽象类继承与依赖注入的自动化配置
c#·.net·代码生成·roslyn
mudtools1 天前
强的飞起的 Roslyn 编译时代码生成,实现抽象类继承与依赖注入的自动化配置
c#·.net