[C#]できるだけ楽に List や Dictionary を初期化する

今回は息抜きに、ちょっとしたコーディングの「省略」を求めたい人向けの記事です。
比較的新しめな record についても触れています。

なお、C# 9.0 以前では使えないものもあります。

List<string>

string の初期化なんて、もともと楽じゃない?

そう思うかもしれません。

    void Start()
    {
        //さすがにこれはやめよう

        //List<string> texts = new List<string>();
        //texts.Add("Taro");
        //texts.Add("Jiro");
        //texts.Add("Saburo");
        //texts.Add("Shiro");

        List<string> texts = new List<string>()
        {
            "Taro",
            "Jiro",
            "Saburo",
            "Shiro",
        };
    }

油断してはいけません。コメント部分の書き方しか知らない、古の C#er もたまにいます。
(大昔の C# だとコメント部分の記述しか許されていなかった)

ちなみに、var を使えばもう少し楽になりますよね。

List<string> texts = new List<string>()
↓
// 1: よく見る省略(タイプセーフ)
var texts = new List<string>()

// 2: こっちは以外と知られていないかも
List<string> texts = new()

C# の var は動的言語のような不安定な型ではないので、安心して使いましょう。
2番目の省略は、クラスの初期化で使うと便利です。後ほど解説します。

Dictionary

これも直感的な書き方ができます。ネストも可能。(やりすぎには注意)

    void Start()
    {
        var dics = new Dictionary<int, string>()
        {
            { 1, "Taro" },
            { 2, "Jiro" },
            { 3, "Saburo" },
            { 4, "Shiro" },
        };

        var dics2 = new Dictionary<int, List<string>>()
        {
            { 1, new() { "Taro",   "太郎" } },
            { 2, new() { "Jiro",   "次郎" } },
            { 3, new() { "Saburo", "三郎" } },
            { 4, new() { "Shiro",  "四郎" } },
        };
    }

List<MyClass>

    class MyClass
    {
        public int    Number;
        public string Name;
    }

    void Start()
    {
        var classes = new List<MyClass>()
        {
            new MyClass() { Number = 1, Name = "Taro"   },
            new MyClass() { Number = 2, Name = "Jiro"   },
            new MyClass() { Number = 3, Name = "Saburo" },
            new MyClass() { Number = 4, Name = "Shiro"  },
        };
    }

このような書き方が基本。
まずは MyClass が鬱陶しいので、省略しましょう。

        var nodes = new List<MyClass>()
        {
            new() { Number = 1, Name = "Taro"   },
            new() { Number = 2, Name = "Jiro"   },
            new() { Number = 3, Name = "Saburo" },
            new() { Number = 4, Name = "Shiro"  },
        };

List<string> の初期化でも触れましたが、MyClass は推論できるので省略可能、というわけです。

次に、Number = と Name = を省略するには……。

    class MyClass
    {
        public int    Number;
        public string Name;

        public MyClass(int number, string name)
        {
            Number = number;
            Name   = name;
        }
    }

    void Start()
    {
        var nodes = new List<MyClass>()
        {
            new (1, "Taro"),
            new (2, "Jiro"),
            new (3, "Saburo"),
            new (4, "Shiro"),
        };
    }

コンストラクタを宣言することで可能ですが、クラスの記述が長くなるのはちょっと気分悪い。

    record MyRecord(int Number, string Name);

    void Start()
    {
        var nodes = new List<MyRecord>()
        {
            new (1, "Taro"),
            new (2, "Jiro"),
            new (3, "Saburo"),
            new (4, "Shiro"),
        };
    }

そこで、record を使いましょう。record の詳しい解説は他のサイトに譲るとしてデータのやりとりに特化したクラスを自動生成してくれるくらいに思ってください。

record はデータのメンバーが全て一致するチェック(Equals)なども自動定義されたり、今後使われるケースが増えるんじゃないかなと思われます。

覚えて損はありません。

unity だとエラーになる

次のコードを書き足すと、とりあえず使うことができます。(保証はされていませんが)

namespace System.Runtime.CompilerServices
{
    internal static class IsExternalInit { }
}

詳しい解説は以下で。

返信を残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA