共用方式為


清單模式

注意

本文是功能規格。 規格可作為功能的設計檔。 其中包含建議的規格變更,以及功能設計和開發期間所需的資訊。 這些文章會發佈,直到提議的規格變更完成並併併入目前的ECMA規格為止。

功能規格與已完成實作之間可能有一些差異。 這些差異已記錄在相關的 語言設計會議(LDM)備忘錄中。

您可以在 規格的文章中深入瞭解將功能說明文件納入 C# 語言標準的過程

冠軍問題:https://github.com/dotnet/csharplang/issues/3435

總結

可讓您比對陣列或清單與一連串的模式。例如,array is [1, 2, 3] 會比對一個包含元素 1、2、3 的長度為三的整數陣列。

詳細設計

模式語法會修改如下:

list_pattern_clause
  : '[' (pattern (',' pattern)* ','?)? ']'
  ;

list_pattern
  : list_pattern_clause simple_designation?
  ;

slice_pattern
  : '..' pattern?
  ;

primary_pattern
  : list_pattern
  | slice_pattern
  | // all of the pattern forms previously defined
  ;

有兩個新的模式:

  • list_pattern 用於匹配元素。
  • slice_pattern 只允許一次,而且只能直接用在 list_pattern_clause 中,以捨棄 零個或多個 元素。

模式相容性

list_pattern 與任何 可計數可索引 的類型相容,因為它具有可存取的索引器,可以接受一個 Index 作為參數,或具有單一 int 參數的可存取索引器。 如果兩個索引器都存在,則偏好使用前者。

具有子模式的 slice_pattern 與可計算 以及 可交叉分析 的任何類型相容,其具有可存取索引器,可存取的索引器會採用 Range 做為自變數,或是具有兩個 int 參數的可存取 Slice 方法。 如果兩者都存在,則偏好使用前者。

沒有子模式的 slice_pattern 適用於任何與 list_pattern相容的類型。

此規則集衍生自 範圍索引器模式

涵蓋性檢查

涵蓋檢查的運作方式就像 具有 ITuple 的位置模式一樣,對應的子模式會依位置進行匹配,並加上一個額外的節點來測試長度。

例如,下列程式代碼會產生錯誤,因為這兩種模式會產生相同的 DAG:

case [_, .., 1]: // expr.Length is >= 2 && expr[^1] is 1
case [.., _, 1]: // expr.Length is >= 2 && expr[^1] is 1

不同於:

case [_, 1, ..]: // expr.Length is >= 2 && expr[1] is 1
case [.., 1, _]: // expr.Length is >= 2 && expr[^2] is 1

未指定運行時間中比對子模式的順序,且失敗的比對可能不會嘗試比對所有子模式。

假設有特定長度,有可能有兩個子模式參考相同的元素,在此情況下,此值的測試會插入決策 DAG 中。

  • 例如,[_, >0, ..] or [.., <=0, _] 會變成 length >= 2 && ([1] > 0 || length == 3 || [^2] <= 0),其中長度值為 3 表示另一個測試。
  • 相反地,[_, >0, ..] and [.., <=0, _] 會變成 length >= 2 && [1] > 0 && length != 3 && [^2] <= 0,其中長度值為 3 不允許進行其他測試。

因此,會產生類似 case [.., p]: case [p]: 的錯誤,因為在執行期間,我們會在第二個案例中比對相同的元素。

如果分割子模式符合清單或長度值,這些子模式會被視為包含清單的直接子模式。 例如,[..[1, 2, 3]] 包含一種 [1, 2, 3]形式的模式。

對使用中的成員作出的下列假設:

  • 只有當型別是 可編製索引時,才假設類型 可計算 的屬性會一律回傳非負值。 例如,模式 { Length: -1 } 永遠無法比對陣列。
  • 假設使類型 可以分割 的成員運行良好,也就是說,返回值從不為空,而且它是所含清單的適當子片段。

如果上述任何假設未保留,模式比對作業的行為是未定義的。

降低

表單 expr is [1, 2, 3] 的模式相當於下列程式代碼:

expr.Length is 3
&& expr[new Index(0, fromEnd: false)] is 1
&& expr[new Index(1, fromEnd: false)] is 2
&& expr[new Index(2, fromEnd: false)] is 3

slice_pattern 就像適當的捨棄,亦即不會針對這類模式發出任何測試,而只會影響其他節點,也就是長度和索引器。 例如,模式 expr is [1, .. var s, 3] 等同於以下程式碼(若透過明確的 IndexRange 支援得以相容時):

expr.Length is >= 2
&& expr[new Index(0, fromEnd: false)] is 1
&& expr[new Range(new Index(1, fromEnd: false), new Index(1, fromEnd: true))] is var s
&& expr[new Index(1, fromEnd: true)] is 3

slice_pattern輸入類型是基礎 this[Range]Slice 方法的傳回 類型,但有兩個例外:針對 string 和陣列,將會分別使用 string.SubstringRuntimeHelpers.GetSubArray

未解決的問題

  1. 我們應該支援多維度陣列嗎? (回答 [LDM 2021-05-26]:不支援。如果我們想要建立以 MD-陣列為主的版本,我們會想要重新審視他們目前不足的所有方面,而不只是列表模式。)
  2. 我們應該接受一般 模式, 遵循 slice_pattern中的 ..? (回答 [LDM 2021-05-26]:是,切片後允許任何模式。)
  3. 根據這個定義,模式 [..] 是測試 expr.Length >= 0的。 我們是否應該省略這類測試,假設 Length 一律為非負數? (回答 [LDM 2021-05-26]:[..] 不會發出長度檢查訊號)