📌

C#11ではリストパターンが使えるようになった。

2022/12/20に公開

概要

C# 11 ではリストパターンが使えるようになりました。
この記事では外部から読み取ったcsv様のデータをパースする例を通して、リストパターンの使い方を確認したいと思います。

リストパターンって?

公式ドキュメントに説明があります。

配列に対して、与えられたパターンに一致するかどうかを確認するパターンです。

csv様のデータをパースする例を通してリストパターンの使い方を確認します。

設定

以下のようなrecordが定義されているとします。

abstract record 部品;
record 部品α(int 縦サイズ, int 横サイズ) : 部品;
record 部品β(int 半径) : 部品;
record 部品γ(string メーカー) : 部品;
record 部品δ(string[] メーカーたち, string メインのメーカー) : 部品;
record 部品ε(int 寸法) : 部品;

外部から読み取った次のようなstring[][]データを、List<部品>にパースしたいとします。

string[][] 生備品リスト = new string[][] {
    new []{"部品β", "3"},
    new []{"部品α","10", "15"},
    new []{"部品β", "4"},
    new []{"部品γ", "A社"},
    new []{"部品β", "8"},
    new []{"部品α", "3", "7"},
    new []{"部品β", "10"},
    new []{"部品δ", "A社", "B社", "C社", "B社"},
    new []{"部品ε", "コメント数3", "10", "コメント:この部品は廃止される", "コメント2:廃止年度は2026年", "コメント3:大体部品の検討中"}
};

コード

以下の書き方で目的が達成できます。

List<部品> 備品リスト = 生備品リスト.Select<string[], 部品>(=>switch
{
    ["部品α", var, var] => new 部品α(int.Parse(), int.Parse()),
    ["部品β", var 半径] => new 部品β(int.Parse(半径)),
    ["部品γ", var メーカー] => new 部品γ(メーカー),
    ["部品δ", .. var メーカーたち, var メインのメーカー] => new 部品δ(メーカーたち, メインのメーカー),
    ["部品ε", _, var 寸法, ..] => new 部品ε(int.Parse(寸法)),
    _ => throw new Exception($"不正なデータ。[{string.Join(' ',)}]はパース出来ません。"),
}).ToList();

出力してみると、正しく読み取れていることがわかります。

foreach (部品 備品 in 備品リスト)
{
    Console.WriteLine(備品);
}

出力:

部品β { 半径 = 3 }
部品α { 縦サイズ = 10, 横サイズ = 15 }
部品β { 半径 = 4 }
部品γ { メーカー = A社 }
部品β { 半径 = 8 }
部品α { 縦サイズ = 3, 横サイズ = 7 }
部品β { 半径 = 10 }
部品δ { メーカーたち = System.String[], メインのメーカー = B社 }
部品ε { 寸法 = 10 }

説明

パターンαの説明

パターン ["a", "b", "c"] は、一番目の要素が"a", 二番目の要素が"b"、三番目の要素が"c"であって、それ以降に要素が続かないような配列にマッチします。
たとえば["部品α", var 縦, var 横]であれば、長さ3の配列であって、一番目の要素が"部品α"であるものにマッチし、2番目の要素が変数、3番目の要素が変数に代入されます。
これにより配列{"部品α","10", "15"}にマッチすることができます。

パターンδの説明

["部品δ", .. var メーカーたち, var メインのメーカー].. は任意長の部分配列を意味します。
この場合、長さが2以上の配列のうち、先頭要素が"部品δのものにマッチし、最後要素が変数メインのメーカーに、その真ん中の要素が配列として変数メーカーたちに代入されます。
これにより配列{"部品δ", "A社", "B社", "C社", "B社"}にマッチすることができます。

パターンεの説明

読む必要のない箇所を読み飛ばすこともできます。

["部品ε", _, var 寸法, ..] => new 部品ε(int.Parse(寸法))は、長さ3以上の配列のうち、先頭要素が "部品ε"のものにマッチし、2番目の要素は無視し、3番目の要素を変数寸法に代入し、4番目以降の要素たちを無視します。
これにより配列{"部品ε", "コメント数3", "10", "コメント:この部品は廃止される", "コメント2:廃止年度は2026年", "コメント3:大体部品の検討中"}にマッチすることができます。

まとめ

C# 11 で導入されたリストパターンの使用例を紹介しました。まだ導入されて日が浅いですが、便利なパターンマッチなので使用例も今後増えてくるかなと思っています。

GitHubで編集を提案

Discussion