2016-11-17 15 views
15

のは、我々が持っているとしましょう:認識されないC#構文

class Foo 
{ 
    public int IntPropertyInFoo { get; set; } 

    public Bar BarPropertyInA { get; set; } 
} 

class Bar 
{ 
    public string StringPropertyInBar { get; set; } 
} 

その後、我々は、オブジェクト初期化子でFooをインスタンス化したいと思います:

public static void Main(string[] args) 
{ 
    var foo = new Foo 
    { 
     IntPropertyInFoo = 123, 
     BarPropertyInA = // Ommiting new and type name - why does it compile? 
     { 
      StringPropertyInBar = "something" 
     } 
    }; 
} 

BarPropertyInAを初期化する構文は、私をバッフル、コードのコンパイルので、警告なしで、実行すると、NullReferenceExceptionをスローします。私はその構文を認識しませんが、プロパティではなくフィールドで使用した場合と同じ効果があるようです。コンパイルされたコードを逆アセンブル

はこれを得られます。

.method public hidebysig static void Main(string[] args) cil managed 
{ 
    .entrypoint 
    // Code size  34 (0x22) 
    .maxstack 3 
    .locals init ([0] class Test.Foo foo) 
    IL_0000: nop 
    IL_0001: newobj  instance void Test.Foo::.ctor() 
    IL_0006: dup 
    IL_0007: ldc.i4.s 123 
    IL_0009: callvirt instance void Test.Foo::set_IntPropertyInFoo(int32) 
    IL_000e: nop 
    IL_000f: dup 
    IL_0010: callvirt instance class Test.Bar Test.Foo::get_BarPropertyInA() 
    IL_0015: ldstr  "something" 
    IL_001a: callvirt instance void Test.Bar::set_StringPropertyInBar(string) 
    IL_001f: nop 
    IL_0020: stloc.0 
    IL_0021: ret 
} // end of method Program::Main 

に似ています:これは、プロパティの/フィールドのメンバーを初期化するためのいくつかの構文糖ことになっている

public static void Main(string[] args) 
{ 
    var foo = new Foo 
    { 
     IntPropertyInFoo = 123 
    }; 

    foo.BarPropertyInA.StringPropertyInBar = "something"; 
} 

、/そのプロパティを提供フィールドはコンストラクタで初期化されますか?

+0

私は常に新しいクラスとリストを自分のクラスコンストラクタに追加しています。 – Gavin

+1

'BarPropertyInA'を新しい' Bar'に設定する 'Foo'用のコンストラクタがあれば、' StringPropertyInBar'プロパティを設定することができます。彼らは 'BarPropertyInA.StringPropertyInBar =" something "' – juharr

+0

のようなものではなく、これと一緒に行きました。私は配列のコンストラクタなどを使って同じことを信じています。 .Netはインスタントアートのコンテキストに基づいて最高のコンストラクタを暗示する – maximdumont

答えて

2

はい、これは、nullではなく空として開始するプロパティを初期化するための並べ替えの略です。ネットコレクションのプロパティは、これの良い例です。

var cmd = new System.Data.SqlClient.SqlCommand() 
{ 
    Parameters = 
    { 
     new System.Data.SqlClient.SqlParameter() { ParameterName = "@p1", Value = "SomValue"} 
    }, 
    CommandText = "select 1 from Table1 where Value = @p1" 
}; 

また、読み取り専用プロパティの値を初期化することもできます。

この記事からほとんどそのまま借用
//compiles and works 
var message = new MailMessage { To = { "[email protected]" } }; 

message = new MailMessage 
{ 
    // won't compile: To is read-only 
    To = new MailAddressCollection { "[email protected]" }, 
}; 

http://www.codeducky.org/even-concise-c-object-initializers/

新レス初期化子の構文を使用すると、あなたのコードはもう少し簡潔にして、読み取り専用のプロパティを設定するための初期化構文を使用することができます。実際、ほとんどの基本クラスライブラリと一般的な.NETパッケージクラスはコレクションプロパティの空のnullパターンに従っているため、ほとんどの場合、それらのために新しくない構文を利用できます。最後に、new-less初期化を使用することは、オブジェクトが初期化されたデフォルトをそのまま残すことを恩恵を受けることを意味します。

関連する問題