2

コレクションプロパティを持つクラスがあります:

class MyClass
{
    public MyCollection Coll { get; private set; }
    public MyClass() { this.Coll = new MyCollection(); }
}

class MyCollection : IList { ... }

現在、クラスの 2 つの異なるインスタンスを作成しています。

var o1 = new MyClass() { Coll = {"1", "2"}};
var o2 = new MyClass() { Coll = new MyCollection() {"1", "2"} };

プロパティのセッターが存在しない(またはこの場合はパブリックにアクセスできない)ため、コンパイラーが後者について不平を言うことを理解しています。ただし、最初は割り当てでもあります-コレクション初期化子ではありますが。

コレクション初期化子は取得専用プロパティに対して許可されていると思います。これらは呼び出しているだけで、実際にはプロパティのゲッターを呼び出していないためですAddIListこれは正しいですか?

4

1 に答える 1

2

あなたの質問から:

コレクション初期化子は [...] を呼び出しAddているだけだと思いIListます。

この仮定は正しいです。コレクション初期化子は、コンパイル中に C# コンパイラがより明示的なものに変換する構文糖衣です。たとえば、次の行です。

var l = new List<int>() { 1, 2 };

実際には次のように翻訳されます。

var l = new List<int>();
l.Add(1);
l.Add(2);

生成された MSIL を見て、これを確認できます (少し簡略化されています)。

newobj      List<System.Int32>..ctor // Create list object.
stloc.0                              // Store list object as local variable "0".
ldloc.0                              // Push local variable "0" onto the stack.
ldc.i4.1                             // Push 4-byte integer constant "1" onto the stack.
callvirt    List<System.Int32>.Add   // Call "Add" (uses and pops the last two values from
                                     // the stack).
ldloc.0                              // Push list onto stack again.
ldc.i4.2                             // Push constant "2" onto stack.
callvirt    List<System.Int32>.Add   // Call "Add" again.

これは、コードvar o1 = new MyClass() { Coll = {"1", "2"}};がプライベート セッターにアクセスしないことを意味します。次のように取得Collして呼び出すだけです。Add

var o1 = new MyClass();
o1.Coll.Add("1");
o1.Coll.Add("2");

ここでも、MSIL をチェックしてこれを確認できます。

newobj      MyClass..ctor
stloc.1                              // Store MyClass instance at local variable "1".
ldloc.1                              // Load MyClass instance onto stack.
callvirt    MyClass.get_Coll         // Call getter of "Coll" and push the MyCollection
                                     // instance onto the stack.
ldstr       "1"                      // Push the string "1" onto the stack...
callvirt    MyCollection.Add         // ...and call "Add".
pop                                  // Discard the return value of "Add".
ldloc.1
callvirt    MyClass.get_Coll
ldstr       "2"
callvirt    MyCollection.Add
pop
于 2016-08-05T15:03:07.157 に答える