串列與切片模式

小提示

本文屬於 基礎部分, 適合已經至少懂一種程式語言並正在學習 C# 的開發者。 如果你不熟悉模式,可以先從 模式比對概觀 開始。 完整的支援型別與語言規則,請參閱語言參考中的 列表模式 。

序列的 形狀 是圖案所需的可觀察性質集合。 這些屬性可能包括元素數量、每個元素或整個元素序列所寫的需求,以及特定索引處的標記值。 例如,一個形狀可能恰好需要兩個元素,索引 "Name" 為 0,或者它可能需要第一個標記、最後一個標記,以及它們之間的非空序列。

列表模式透過結合元素數量要求與有序位置的巢狀圖案來描述形狀。 它只測試模式中寫下的需求:元素子模式測試其對應元素,而 切片模式 則允許或測試一連串原本不匹配的元素。 你可以使用這些部分來比對確切的計數和標記值、擷取固定位置的值、允許中間部分不必匹配,或將巢狀模式套用至該中間部分。

當輸入的編譯時期型別具有 Length 或 Count 屬性,並支援索引式元素存取(也就是可依元素位置擷取元素)時,請選擇清單模式,如 input[index]。 陣列、List<T>字串和跨度是常見的範例。 編譯器會根據變數宣告的編譯時型別判斷資格,因為必須在程式執行前解析這些所需成員。 IEnumerable<T>介面本身提供列舉,而非這些成員,即使執行時物件是可索引的集合。

列表模式使用長度或計數及索引元素存取來取代列舉。 對於常見的內建型別,匹配只能檢查由模式命名的位置,而不必遍歷每個元素。 這些操作的成本取決於輸入類型。 迭代一個長集合可能需要時間,因此當決策需要檢視任意數量的元素而非特定位置時,建議使用迴圈或 LINQ。

完全匹配形狀

以下方法辨識雙欄標頭:

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

表達式 columns 就是模式輸入。 ["Name", "Score"] 包含兩個常數模式。 精確列表模式省略切片模式,需要恰好兩個元素,並將每個巢狀模式套用到同一索引的元素上。 此模式描述具有確切數量和兩個標記值的形狀:索引 0 處為 "Name",索引 1 處為 "Score"。 巢狀元素模式為可選:空清單模式 [] 描述並匹配無元素的序列。

當形狀結合元素數量與有序位置的需求時,選擇列表模式。 如果只有元素數量才重要,則 a Length 或 Count 性質模式, items is { Count: 0 }例如 ,會更直接地表達這個意圖。

使用 discard 比對任何元素值

以下方法會從包含三個名字的完賽排序中讀取冠軍和第三名(季軍):

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 winnervar 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 處有 "BEGIN" 標記,並在最後一個索引處有 "END"。 屬性模式 { Length: > 0 } 接著對切片匹配的序列增加了一個要求:它必須包含至少一個元素。 這些要求共同描述了完整的形狀。 這個圖案不會測試切片內元素的數值。

只有在中間部分本身需要進行比對或擷取時,才使用切片子模式。 如果只有邊界元素重要,普通元素 .. 就比較簡單。

另請參閱