列表和切片模式

Tip

本文是已了解至少一种编程语言并正在学习 C# 的开发人员的 “基础知识 ”部分的一部分。 如果模式不熟悉,请从 模式匹配概述 开始。 有关完整的支持类型和语言规则,请参阅语言参考中的 列表模式 。

序列 的形状 是模式所需的一组可观察属性。 这些属性可以包括元素数、为每个元素编写的要求或整个元素序列的要求,以及特定索引处的标记值。 例如,某个形状可能要求恰好有两个元素,且索引 0 处为"Name";或者,它可能要求一个第一个标记、一个最后一个标记,以及它们之间的一个非空序列。

列表模式通过将元素计数要求与有序位置的嵌套模式组合在一起来描述形状。 它仅测试模式中编写的要求:元素子模式测试其相应的元素,而 切片模式 可以允许或测试一系列其他不匹配的元素。 可以使用这些部分来匹配确切的计数和标记值、捕获固定位置的值、允许不匹配的中间值,或将嵌套模式应用于该中间。

当输入的编译时类型提供 Length 或 Count 属性和索引元素访问时,请选择列表模式,该访问按其位置检索元素,如中 input[index]所示。 数组、 List<T>字符串和范围是常见示例。 编译器从变量的声明编译时类型确定资格,因为它必须在程序运行之前解析这些必需的成员。 即使 IEnumerable<T> 运行时对象是可索引集合,接口本身也提供枚举而不是这些成员。

列表模式使用长度或计数和索引元素访问,而不是枚举。 对于常见的内置类型,匹配只能检查模式命名的位置,而不是循环访问每个元素。 这些操作的成本取决于输入类型。 遍历较长的集合可能会比较耗时,因此,如果判断需要检查任意数量的元素,而不是特定位置上的元素,则应使用循环或 LINQ。

匹配精确形状

以下方法可识别两列标题:

static bool IsHeader(string[] columns) =>
    columns is ["Name", "Score"];

表达式 columns 是模式输入。 ["Name", "Score"] 包含两个常量模式。 确切的列表模式省略切片模式,需要恰好两个元素,并将每个嵌套模式应用于同一索引处的元素。 此模式描述具有精确计数和两个标记值的形状: "Name" 索引 0 和 "Score" 索引 1。 嵌套元素模式是可选的:空列表模式 [] 描述和匹配无元素的序列。

当形状将元素计数与有序位置的要求组合在一起时,请选择列表模式。 如果只有元素数量才重要,那么使用 Length 或 Count 属性模式(例如 items is { Count: 0 })可以更直接地表达这一意图。

使用弃元来匹配任意元素值

以下方法从一个包含三个名字的完赛顺序中读取冠军和季军:

static string GetAnnouncements(List<string> finishingOrder) =>
    finishingOrder switch
    {
        [var winner, _, var thirdPlace] =>
            $"Winner: {winner}; third place: {thirdPlace}",
        _ => "A complete three-runner result isn't available"
    };

var winner 模式和 var thirdPlace 模式各声明一个变量。 当列表模式匹配时,C# 将匹配的元素值分配给相应的变量,以便结果可以使用 winner 和 thirdPlace。 放弃模式 _ 接受第二个元素并放弃其值。 此形状需要确切的三个元素,并提供第一和第三个位置的特定含义,但它不需要任何位置的特定值。

当固定位置的含义固定时,请选择此表单。 如果需要检查任意数量的元素、转换序列、在整个序列中搜索或执行聚合,请使用循环或 LINQ。

允许剩余元素使用切片模式

在这个简化示例中,命令行可以以 --verbose 开头,并包含其他参数,且假定以输入文件名结尾。 以下方法识别在最后一个位置具有文件名的形状,并捕获该值:

static string GetInputFile(string[] arguments) =>
    arguments switch
    {
        ["--verbose", .., var fileName] => $"Verbose processing: {fileName}",
        [.., var fileName] => $"Processing: {fileName}",
        [] => "No input file was provided"
    };

切片模式..允许第一个和最后一个元素模式之间的零个或多个剩余元素。 列表模式最多可以包含一个切片模式。 第一个开关臂描述至少包含两个元素的形状:索引 0 处的标记 "--verbose" 、最后一个位置的文件名以及它们之间的任意数量的不匹配参数。 独立切片不会测试这些中间参数。 第二个臂接受任何无空形状并捕获其最后一个元素,而空图案处理没有元素的序列。

切片可以出现在列表模式的开头、中间或末尾。 当可变长度序列是形状的一部分,但只有周围的位置需要元素测试时使用它。 当每个元素需要处理时,请使用普通迭代。

将模式应用于切片

可以将另一种模式应用于匹配的 ..部件。 以下方法用于测试数组是否以 "BEGIN" 开头、以 "END" 结尾,并且两者之间至少有一个元素:

static bool HasContent(string[] entries) =>
    entries is ["BEGIN", .. { Length: > 0 }, "END"];

外层模式首先要求在索引 0 处有标记 "END",并在最后一个索引处有标记 "BEGIN"。 然后,属性模式 { Length: > 0 } 增加了切片匹配的序列的要求:它必须至少包含一个元素。 这些要求共同描述了完整的形状。 该模式不会测试切片中元素的值。

仅当中间部分本身需要测试或捕获时,才使用切片子模式。 如果只有边界元素重要,直接使用 .. 会更简单。

另见