2016-08-10 4 views
1

オブジェクト初期化子を使用している間に、誤って配列初期化子でICollectionをインスタンス化しようとしました(私はnew ...部分を忘れました)。非常に奇妙なのは、コンパイラがコンパイル時に不平を言うのではなく、実行時にNullReferenceExceptionが発生したことです。ここで配列初期化子はコンパイル時に有効ですが、オブジェクト初期化子の内部で実行時に失敗します

は、状況を要約するためにいくつかのコードです:もちろん

public class FakeClass 
{ 
    public ICollection<string> StringsCollection { get; set; } 

    public string[] StringsArray { get; set; } 
} 

FakeClass c = new FakeClass(); 
c.StringsCollection = { "test" }; // doesn't compile - ok 
c.StringsCollection = new string[] { "test" }; // compiles - ok 
c.StringsArray = { "test" }; // doesn't compile - ok 
c.StringsArray = new string[] { "test" }; // compiles - ok 

string[] strings = { "sdfqgrt" }; // compiles - ok 
strings = { "sdfqgrt" }; // doesn't compile - ok 

FakeClass c2 = new FakeClass 
{ 
    StringsCollection = { "rthtj" }, // compiles and throws at run - why? 
    StringsArray = { "egryjt" } // doesn't compile - ok 
}; 

このコードを実行することはできませんが、私は、コンパイラはそのようなことを受け入れることができる方法についての好奇心、なぜ私はを理解しています。

+0

ICollectionを初期化しない{get; set}を使用しています。クラスのコンストラクタに初期化を追加するか、またはreplace {get; set ;;}コンストラクタへの呼び出しで:new ICollection () – jdweng

+0

イニシャライザは素晴らしいシンタックスシュガーを使用しますが、あまりにも多くの砂糖は腐った歯を生成する傾向があります。構文が有効で、*コレクション*初期化子(フィールド初期化子ではありません)を使用していますが、Add()メソッドのみが必要です。したがって、コレクション参照を取得するためにsetterを呼び出すのではなく、* getter *を呼び出します。これはnullです。このような間違いを避けることは簡単ではありません。学校のハードノックに参加する必要があります。 –

答えて

2
StringsCollection = { "rthtj" } 

このコードで何も問題はありません。暗黙的にAddメソッドを呼び出し、その文字列をコレクションに追加します。

あなたのプロパティがまだ初期化されていないため、NRE例外です。これは、このコードではコメント

にIL上

FakeClass c = new FakeClass(); 
c.StringsCollection = new string[] { "test" }; 

FakeClass c2 = new FakeClass 
{ 
    StringsCollection = { "dd" } 
}; 

ルックに答え、最初の間で異なることに注意を払うように

public ICollection<string> StringsCollection { get; set; } = new List<string>(); 

アップデートに動作します

と第2のStringCollection

あなたはコレクション初期化子を使用しgetterケースのために)new string[] {}たり、新しいリスト(のような式を必要とするsetter場合については

IlSpy

+0

実際、どこかで、 'Add'メソッドが呼び出されたのを見ました。しかし、なぜ 'c.StringsCollection = {" test "};'はコンパイルされていないのでしょうか? –

関連する問題