欢迎光临散文网 会员登陆 & 注册

C# 分片模式

2023-01-16 10:41 作者:SunnieShine  | 我要投稿

1、语法

C# 允许对集合类型的分片。举个例子。

这段代码表示,我们将中间的 8 个元素提取出来,变成一个列表。它等价于这个写法:

一定要注意,1..^1 的语义是“取[1][^2] 的元素,而绝对不是取到 ^1。因为 C# 的范围表达式是取前不取后的(前闭后开的半开区间)。

2、分片模式的弃元

分片模式也支持弃元。换句话说,我们可以在 .. 后跟上 _ 来表示这一截内容我们不参与模式匹配,它和不写弃元符号的时候匹配的内容是完全一致的,只是为了确保语法的灵活性:

这里的 .. __ 就是弃元用法。不过它没有意义,可以省略。

3、分片模式解构及嵌套模式匹配

分片模式允许我们对范围记号 .. 的内容进行内联变量定义,但这样的代码仍不够灵活。我还想要内联模式匹配的话,C# 是提供了这个机制的。看看这样的代码是什么意思?

是的,在模式匹配 [_, _, .. [_, .., 7], _] 的模式。这个模式要求我们列表集合里至少含有三个以上的元素。接着,.. [_, .., 7] 是分片模式的嵌套模式匹配。我们从第三个元素开始判断,我们必须要求从第三个元素开始,我们包含一个序列,它至少有两个元素,且最后一个元素是 7。换句话说,它等价于这样的代码:

注意这里的判断模式。我们用到了三个逻辑表达式,且使用 && 运算符连起来。下面来说一下挨个的具体判断内容。

  • 第一个表达式 arr is { Length: >= 3 } 判断整个数组是不是不为 null 的同时还至少包含 3 个元素。注意这里 arr 虽然显然不空,但编译器会自动确保引用类型不空而自动产生该 is not null 的模式匹配代码;

  • 第二个表达式 arr[2..^1] is { Length: >= 2 } sliced 较为复杂。它先获取 arr 从第 2 索引元素(第 3 个元素)到倒数第二个元素(一定注意索引运算符是取前不取后的)。这个操作如果获取成功,则返回正常数组,否则会返回 null。因此这个 is { Length: >= 2 } 验证了 arr[2..^1] 是否在取分片数组的时候返回结果是否不为 null。如果不为空还要判断它的长度是不是至少包含 2 个元素。接着,如果两个判断逻辑都成功的话,那么 sliced 变量就可以使用了,它就是这个分片后的数组结果;

  • 第三个表达式 sliced[^1] == 7 就是获取整个数组的最后一个元素,看看是不是 7。

所以整个表达式稍显复杂,但按顺序来看的话,就不会有任何问题了。

4、列表和分片模式的范围记号 .. 最多只能有一个

虽然有些时候我们很想写这样的代码:

我们的想法是,元素至少有一个,且整个序列里至少有一个元素的结果是 40。

可,C# 编译器并不理解这样的语法,它认为 .. 的长度不定,因此无法叠加使用,否则将无法确保使用的严谨性,比如这样的代码:

这个 [.., 10, 20, ..] 就无法理解。而且,这样的代码也是没有意义的:

连续使用两个范围记号 ..。因此,请一定记住,列表和分片模式的范围记号最多只能有一个。不过,这种不影响:

这种是分片之后判断序列的模式是 [.., _],因此这个是可以的,因为不会冲突。

5、分片模式里的模式嵌套

如果这个数组的每一个元素并不是简单的类型,那么它里面可能包含一些别的元素。这个时候我们可能会在分片后,使用别的模式进行模式匹配:

比如这里 .. [{ Prop: 42 } sliced, ..] 就是一个典型的嵌套用法。.. 后跟上 [{ Prop: 42 } sliced, ..] 是一个嵌套进去的分片模式。其中,它判断分片后的序列至少包含 1 个元素,且第一个元素必须满足模式 { Prop: 42 } sliced,也就是 Prop 属性必须是 42。如果成功匹配,那么这个元素名称可以使用 sliced 标识符引用。

C# 分片模式的评论 (共 条)

分享到微博请遵守国家法律