C# 分片模式
1、語法
C# 允許對(duì)集合類型的分片。舉個(gè)例子。
這段代碼表示,我們將中間的 8 個(gè)元素提取出來,變成一個(gè)列表。它等價(jià)于這個(gè)寫法:
一定要注意,1..^1
的語義是“取[1]
到 [^2]
的元素,而絕對(duì)不是取到 ^1
。因?yàn)?C# 的范圍表達(dá)式是取前不取后的(前閉后開的半開區(qū)間)。
2、分片模式的棄元
分片模式也支持棄元。換句話說,我們可以在 ..
后跟上 _
來表示這一截內(nèi)容我們不參與模式匹配,它和不寫棄元符號(hào)的時(shí)候匹配的內(nèi)容是完全一致的,只是為了確保語法的靈活性:
這里的 .. _
的 _
就是棄元用法。不過它沒有意義,可以省略。
3、分片模式解構(gòu)及嵌套模式匹配
分片模式允許我們對(duì)范圍記號(hào) ..
的內(nèi)容進(jìn)行內(nèi)聯(lián)變量定義,但這樣的代碼仍不夠靈活。我還想要內(nèi)聯(lián)模式匹配的話,C# 是提供了這個(gè)機(jī)制的??纯催@樣的代碼是什么意思?
[_, _, .. [_, .., 7], _]
的模式。這個(gè)模式要求我們列表集合里至少含有三個(gè)以上的元素。接著,.. [_, .., 7]
注意這里的判斷模式。我們用到了三個(gè)邏輯表達(dá)式,且使用 &&
運(yùn)算符連起來。下面來說一下挨個(gè)的具體判斷內(nèi)容。
第一個(gè)表達(dá)式
arr is { Length: >= 3 }
判斷整個(gè)數(shù)組是不是不為null
的同時(shí)還至少包含 3 個(gè)元素。注意這里arr
雖然顯然不空,但編譯器會(huì)自動(dòng)確保引用類型不空而自動(dòng)產(chǎn)生該is not null
的模式匹配代碼;第二個(gè)表達(dá)式
arr[2..^1] is { Length: >= 2 } sliced
較為復(fù)雜。它先獲取arr
從第 2 索引元素(第 3 個(gè)元素)到倒數(shù)第二個(gè)元素(一定注意索引運(yùn)算符是取前不取后的)。這個(gè)操作如果獲取成功,則返回正常數(shù)組,否則會(huì)返回null
。因此這個(gè)is { Length: >= 2 }
驗(yàn)證了arr[2..^1]
是否在取分片數(shù)組的時(shí)候返回結(jié)果是否不為null
。如果不為空還要判斷它的長(zhǎng)度是不是至少包含 2 個(gè)元素。接著,如果兩個(gè)判斷邏輯都成功的話,那么sliced
變量就可以使用了,它就是這個(gè)分片后的數(shù)組結(jié)果;第三個(gè)表達(dá)式
sliced[^1] == 7
就是獲取整個(gè)數(shù)組的最后一個(gè)元素,看看是不是 7。
所以整個(gè)表達(dá)式稍顯復(fù)雜,但按順序來看的話,就不會(huì)有任何問題了。
4、列表和分片模式的范圍記號(hào) ..
最多只能有一個(gè)
雖然有些時(shí)候我們很想寫這樣的代碼:
我們的想法是,元素至少有一個(gè),且整個(gè)序列里至少有一個(gè)元素的結(jié)果是 40。
可,C# 編譯器并不理解這樣的語法,它認(rèn)為 ..
的長(zhǎng)度不定,因此無法疊加使用,否則將無法確保使用的嚴(yán)謹(jǐn)性,比如這樣的代碼:
[.., 10, 20, ..]
..
這種是分片之后判斷序列的模式是 [.., _]
,因此這個(gè)是可以的,因?yàn)椴粫?huì)沖突。
5、分片模式里的模式嵌套
如果這個(gè)數(shù)組的每一個(gè)元素并不是簡(jiǎn)單的類型,那么它里面可能包含一些別的元素。這個(gè)時(shí)候我們可能會(huì)在分片后,使用別的模式進(jìn)行模式匹配:
.. [{ Prop: 42 } sliced, ..]
就是一個(gè)典型的嵌套用法。..
后跟上 [{ Prop: 42 } sliced, ..]
是一個(gè)嵌套進(jìn)去的分片模式。其中,它判斷分片后的序列至少包含 1 個(gè)元素,且第一個(gè)元素必須滿足模式 { Prop: 42 } sliced
,也就是 Prop
屬性必須是 42。如果成功匹配,那么這個(gè)元素名稱可以使用 sliced