プログラムを中心とした個人的なメモ用のブログです。 タイトルは迷走中。
内容の保証はできませんのであしからずご了承ください。

2019/11/06

[C#] テーブル駆動方式の実装方法

update2019/12/09 event_note2019/11/06 3:55

テーブル駆動方式とは、コード・コンプリートで紹介されている実装方法で、データの組み合わせを配列等であらかじめ定義しておくことで、ロジックをシンプルにすることができる方法です。

テーブル駆動方式の解説は省略しますが、C# ではどのような実装方法があるか試してみました。
尚、実行速度は考慮していません。

Dictionary を入れ子にする

まず最初に思いついたのがこれです。

enum HogeKey
{
    Key1, Key2, Key3, Key4
}

enum PiyoKey
{
    Key1, Key2, Key3, Key4
}

public static void Main()
{
    var foo = new Dictionary<HogeKey, Dictionary<PiyoKey, string>>()
    {
        {
            HogeKey.Key1, new Dictionary<PiyoKey, string>
            {
                { PiyoKey.Key1, "Hoge1Piyo1"},
                { PiyoKey.Key2, "Hoge1Piyo2"}
            }
        },
    };

    Console.WriteLine(foo[HogeKey.Key1][PiyoKey.Key1]);
}

個人的には、初期化子はインデクサーを使って書く方が、KeyValue の対比が見やすくなるので好きです。

var foo = new Dictionary<HogeKey, Dictionary<PiyoKey, string>>()
{
    [HogeKey.Key1] =
    {
        [PiyoKey.Key1] = "Hoge1Piyo1",
        [PiyoKey.Key2] = "Hoge1Piyo2"
    }
};

タプルを使う

テーブルが多次元であれば、Dictionary より Tuple のほうがネストが浅くなって良いかもしれません。

enum HogeKey
{
    Key1, Key2, Key3, Key4
}

enum PiyoKey
{
    Key1, Key2, Key3, Key4
}

public static void Main()
{
    var foo = new Dictionary<Tuple<HogeKey, PiyoKey>, string>()
    {
        {
            new Tuple<HogeKey,PiyoKey>(HogeKey.Key1, PiyoKey.Key1),
            "Hoge1Piyo1"
        },
        {
            new Tuple<HogeKey,PiyoKey>(HogeKey.Key1, PiyoKey.Key2),
            "Hoge1Piyo2"
        },
    };

    Console.WriteLine(foo[new Tuple<HogeKey, PiyoKey>(HogeKey.Key1, PiyoKey.Key1)]);
}

こちらも、インデクサーとタプルのシンタックスシュガーを使えば以下のように簡単に書けます。

var foo = new Dictionary<(HogeKey, PiyoKey), string>()
{
    [(HogeKey.Key1, PiyoKey.Key1)] = "Hoge1Piyo1",
    [(HogeKey.Key1, PiyoKey.Key2)] = "Hoge1Piyo2"
};

Console.WriteLine(foo[(HogeKey.Key1, PiyoKey.Key1)]);

JSON を使う

テーブルのデータを JSON ファイルで用意する方法です。
デシリアライズする手間とかはありますが、データとロジックが完全に分離されるので、結構良いと思います。

個人的な結論

  • 階層構造を明確に表現したい場合は Dictionary
  • 複合主キーのように使いたい場合は Tuple
  • データを変更することがある場合は JSON

が良いかなぁと思っています。