none
C# 「コレクション初期化子」言語仕様について RRS feed

  • 質問

  • ※オペレーター注:「(C#)オブジェクト初期化子について」への返信から新たに質問のスレッドを作成しました。
    ---

    相乗りの質問で申し訳ありません。「言語仕様」に係る疑問なのですが・・・

    外池と申します。

    言語仕様によると、コレクション初期化をするにあたって、IEnumerableを備えていることが求められています。しかし、この要求だけだと、Addメソッドが存在することと繋がらないと思うのですが。

    追記:

    失礼・・・、Addメソッドが必要と書かれていますね。この点は納得。逆に、IEnumerableが必要なのか? という疑問。


    • 編集済み 外池 2016年6月28日 6:38
    • 分割 星 睦美 2016年6月29日 2:24 新しい質問者
    • 編集済み 星 睦美 2016年6月29日 2:28 スレッド作成
    2016年6月28日 6:24

回答

  • C# 言語仕様 Version 5.0(日本語版)の7.6.10.3「コレクション初期化子」には以下の記述があります。

    コレクション初期化子が適用されるコレクション オブジェクトは、System.Collections.IEnumerable を実装する型である必要があります。この型でない場合は、コンパイル エラーが発生します。順に指定された要素ごとに、コレクション初期化子によりターゲット オブジェクトで要素初期化子の式リストを引数リストとして Add メソッドが呼び出され、各呼び出しに標準のオーバーロードの解決が適用されます。したがって、コレクション オブジェクトには、各要素初期化子に対する適切な Add メソッドが含まれている必要があります。

    IEnumerableに加えてAddメソッドの実装も要求しています。

    // 実装的にはIEnumerableの方こそ不要なのだけど、コレクションであることを意味させるためなんだろうな。

    ちなみに、こういう特定シグネチャのメソッドを実装していることを要求する物としては他にforeachなんかもありますね(IEnumerator GetEnumerator()またはIEnumerator<T> GetEnumerator()を持っている必要がある。IEnumerable/IEnumerable<T>を継承している必要は無い)。

    • 回答としてマーク 外池 2016年6月29日 4:10
    2016年6月28日 6:46
  • メソッド名がAddであればなんでもかまいません。例えばNameValueCollectionクラスにはAddメソッドが2種類存在しますが、そのどちらも使用することができます。もちろん混在も可能です。

    var nvc1 = new NameValueCollection();
    var nvc2 = new NameValueCollection {
        nvc1,
        { "abc", "def" },
    };
    

    • 回答としてマーク 外池 2016年6月29日 4:10
    2016年6月28日 9:48

すべての返信

  • C# 言語仕様 Version 5.0(日本語版)の7.6.10.3「コレクション初期化子」には以下の記述があります。

    コレクション初期化子が適用されるコレクション オブジェクトは、System.Collections.IEnumerable を実装する型である必要があります。この型でない場合は、コンパイル エラーが発生します。順に指定された要素ごとに、コレクション初期化子によりターゲット オブジェクトで要素初期化子の式リストを引数リストとして Add メソッドが呼び出され、各呼び出しに標準のオーバーロードの解決が適用されます。したがって、コレクション オブジェクトには、各要素初期化子に対する適切な Add メソッドが含まれている必要があります。

    IEnumerableに加えてAddメソッドの実装も要求しています。

    // 実装的にはIEnumerableの方こそ不要なのだけど、コレクションであることを意味させるためなんだろうな。

    ちなみに、こういう特定シグネチャのメソッドを実装していることを要求する物としては他にforeachなんかもありますね(IEnumerator GetEnumerator()またはIEnumerator<T> GetEnumerator()を持っている必要がある。IEnumerable/IEnumerable<T>を継承している必要は無い)。

    • 回答としてマーク 外池 2016年6月29日 4:10
    2016年6月28日 6:46
  • なるほど・・・。

    必要な「Addメソッド」は、ただAddメソッドであれば良いのでしょうか・・・。
    2016年6月28日 6:56
  • メソッド名がAddであればなんでもかまいません。例えばNameValueCollectionクラスにはAddメソッドが2種類存在しますが、そのどちらも使用することができます。もちろん混在も可能です。

    var nvc1 = new NameValueCollection();
    var nvc2 = new NameValueCollection {
        nvc1,
        { "abc", "def" },
    };
    

    • 回答としてマーク 外池 2016年6月29日 4:10
    2016年6月28日 9:48
  • プリプロセッサのように、事前にAddメソッドを使った文(複数)に展開されて、その上でコンパイルが走るわけですね? なので、メソッド名がAddであればなんでも構わない・・・、と。

    この理解でOKですか?
    2016年6月28日 11:51