サーチ…


備考

この構文的な砂糖を使用してオブジェクトを初期化する唯一の要件は、型がSystem.Collections.IEnumerableAddメソッドを実装することです。コレクション初期化子と呼ばれますが、オブジェクトはコレクションである必要はありませ

コレクションの初期化子

コレクション型を値で初期化する:

var stringList = new List<string>
{
    "foo",
    "bar",
};

コレクション初期化子は、 Add()呼び出しの構文砂糖です。上記のコードは次のものと同等です:

var temp = new List<string>();
temp.Add("foo");
temp.Add("bar");
var stringList = temp;

競合状態を避けるために、初期化は一時変数を使用して原子的に行われることに注意してください。

Add()メソッドで複数のパラメータを提供する型の場合は、コンマ区切りの引数を中括弧で囲みます。

var numberDictionary = new Dictionary<int, string>
{
    { 1, "One" },
    { 2, "Two" },
};

これは次のようになります。

var temp = new Dictionary<int, string>();
temp.Add(1, "One");
temp.Add(2, "Two");
var numberDictionarynumberDictionary = temp;

C#6インデックスイニシャライザ

C#6以降、インデクサを持つコレクションは、代入するインデックスを角括弧で指定し、その後に等号とそれに続く値を指定することで初期化できます。

辞書の初期化

辞書を使ったこの構文の例:

var dict = new Dictionary<string, int>
{
    ["key1"] = 1,
    ["key2"] = 50
};

これは次のようになります。

var dict = new Dictionary<string, int>();
dict["key1"] = 1;
dict["key2"] = 50

C#6より前にこれを行うコレクション初期化子の構文は次のとおりです。

var dict = new Dictionary<string, int>
{
    { "key1", 1 },
    { "key2", 50 }
};

これは、

var dict = new Dictionary<string, int>();
dict.Add("key1", 1);
dict.Add("key2", 50);

したがって、新しい構文では、初期化されたオブジェクトのインデクサーを使用してAdd()メソッドを使用する代わりに値を割り当てるため、機能に大きな違いがあります。つまり、新しい構文では一般公開されているインデクサのみが必要であり、それを持つオブジェクトであれば動作します。

public class IndexableClass
{
    public int this[int index]
    {
        set 
        { 
            Console.WriteLine("{0} was assigned to index {1}", value, index);
        }
    }
}

var foo = new IndexableClass
{
    [0] = 10,
    [1] = 20
}

これは出力します:

10 was assigned to index 0
20 was assigned to index 1

カスタムクラスのコレクション初期化子

クラスがコレクション初期化子をサポートするようにするには、 IEnumerableインターフェイスを実装し、少なくとも1つのAddメソッドを持たなければなりません。 C#6以降、 IEnumerableを実装しているコレクションは、拡張メソッドを使用してカスタムAddメソッドで拡張できます。

class Program
{
    static void Main()
    {
        var col = new MyCollection {
            "foo",
            { "bar", 3 },
            "baz",
            123.45d,
        };
    }
}

class MyCollection : IEnumerable
{
    private IList list = new ArrayList();

    public void Add(string item)
    {
        list.Add(item)
    }

    public void Add(string item, int count)
    {
        for(int i=0;i< count;i++) {
            list.Add(item);
        }
    }

    public IEnumerator GetEnumerator()
    {
        return list.GetEnumerator();
    }
}

static class MyCollectionExtensions
{
    public static void Add(this MyCollection @this, double value) => 
        @this.Add(value.ToString());
}

パラメータ配列を持つコレクション初期化子

通常のパラメータとパラメータ配列を混在させることができます:

public class LotteryTicket : IEnumerable{
    public int[] LuckyNumbers;
    public string UserName;

    public void Add(string userName, params int[] luckyNumbers){
        UserName = userName;
        Lottery = luckyNumbers;
    }
}

この構文は現在可能です:

var Tickets = new List<LotteryTicket>{
    {"Mr Cool"  , 35663, 35732, 12312, 75685},
    {"Bruce"    , 26874, 66677, 24546, 36483, 46768, 24632, 24527},
    {"John Cena", 25446, 83356, 65536, 23783, 24567, 89337}
}

オブジェクトイニシャライザ内でのコレクション初期化子の使用

public class Tag
{
    public IList<string> Synonyms { get; set; }
}

Synonymsはコレクション型のプロパティです。 Tagオブジェクトがオブジェクトイニシャライザ構文を使用して作成されるとき、 Synonymsはコレクションイニシャライザ構文で初期化することもできます。

Tag t = new Tag 
{
    Synonyms = new List<string> {"c#", "c-sharp"}
};

コレクションプロパティは読み取り専用で、コレクションの初期化構文をサポートします。この変更された例を考えてみましょう( Synonymsプロパティはプライベートセッターを持っています):

public class Tag
{
    public Tag()
    {
        Synonyms = new List<string>();
    }
    
    public IList<string> Synonyms { get; private set; }
}

次のように新しいTagオブジェクトを作成できます:

Tag t = new Tag 
{
    Synonyms = {"c#", "c-sharp"}
};

これは、コレクションの初期化子がAdd()への呼び出しよりも構文的な砂糖にすぎないために機能します。ここでは新しいリストは作成されません。コンパイラは、既存のオブジェクトにAdd()を呼び出すだけです。



Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow