2009-04-11 24 views

答えて

189

オブジェクト初期化子は、オブジェクトを使用しているときに何かがオブジェクトの構築を簡単にするために、C#3に添加しました。

0個以上のパラメータを指定して実行され、オブジェクトの作成と初期化に使用されるコンストラクタの前に、の呼び出しメソッドが作成されたオブジェクトのハンドルを取得します。例えばこの場合

MyObject myObjectInstance = new MyObject(param1, param2); 

MyObjectのコンストラクタは、値param1param2で実行されるであろう。これらは両方ともメモリー内に新しいMyObjectを作成するために使用されます。作成されたオブジェクト(これらのパラメータを使用して設定されたオブジェクト)が返され、myObjectInstanceに設定されます。

一般に、オブジェクトを完全にセットアップするために必要なパラメータがコンストラクタに必要なので、オブジェクトを無効な状態で作成することはできません。

しかし、設定することができるが、必須ではない「余分な」プロパティがしばしばあります。これは、オーバーロードされたコンストラクタによって処理される可能性がありますが、多くの状況で必ずしも有用ではないコンストラクタがたくさんあることにつながります。

これは、初期化子オブジェクトにつながる - 初期化子はあなたが何かでそれを使用することができ、それが構築されています後、あなたのオブジェクト上のプロパティまたはフィールドを設定しますが、することができますオブジェクトを。たとえば:あなたはこれを行うかのように

MyObject myObjectInstance = new MyObject(param1, param2) 
{ 
    MyProperty = someUsefulValue 
}; 

これはほぼ同じ動作をします:

MyObject myObjectInstance = new MyObject(param1, param2); 
myObjectInstance.MyProperty = someUsefulValue; 

をしかし、にマルチスレッドは、オブジェクト初期化子の原子は、それ以来、有益であるかもしれない環境オブジェクトが完全に初期化されていない状態にならないようにします(詳細はthis answerを参照)。これは、意図したようにnullまたは初期化されています。

また、オブジェクト初期化子は(特に複数の値を設定すると)読み易いため、多くのオーバーロードがそのクラスのAPIを複雑にする必要はなく、コンストラクタで多くのオーバーロードと同じ利点が得られます。

+22

私は同意しますが、オブジェクトのイニシャライザは私の文のように1行のコード(きれいに書式化されている)と見なされるので、特にネストされた構造を持っていると、デバッグオブジェクトのイニシャライザが痛いことがあります。 – CrnaStena

+0

@ Reed-Copsey非常に良い説明は、オブジェクトの初期化子でパフォーマンスの向上はありますか、それとも可読性のためだけですか? – Mahender

+2

@Mahender実際には、オブジェクトイニシャライザを使用すると、通常は(非常に小さい)パフォーマンス損失があります。コンストラクターを効率的に書くことができます。 –

40

コンストラクタは、指定された数のパラメータを取り、オブジェクトの作成と初期化に使用される型の定義済みのメソッドです。

オブジェクト初期化子は、コンストラクタの後でオブジェクト上で実行されるコードであり、オブジェクトの任意の数のフィールドを指定された値に簡潔に設定するために使用できます。これらのフィールドの設定は、の後にとなり、コンストラクターが呼び出されます。

コンストラクタがオブジェクトの初期状態を十分に設定している場合は、オブジェクト初期化子の助けを借りずにコンストラクタを使用します。ただし、オブジェクト初期化子はコンストラクタとともに使用する必要があります。この構文では、初期オブジェクトを作成するために、コンストラクタの明示的または暗黙的な使用(VB.NetおよびC#)が必要です。コンストラクタがオブジェクトを使用目的に十分に初期化せず、いくつかの簡単なフィールドおよび/またはプロパティセットを作成する場合は、オブジェクト初期化子を使用します。

+13

"after"ノートが重要です、ありがとう – user8032

4

コンストラクタは、パラメータを受け取り、クラスの新しいインスタンスを返すメソッドです(可能性があります)。初期化ロジックを含むことがあります。 以下に、コンストラクタの例を示します。


public class Foo 
{ 
    private SomeClass s; 
    public Foo(string s) 
    { 
     s = new SomeClass(s); 
    } 
} 

さて、次の例を考えてみます。


public class Foo 
{ 
    public SomeClass s { get; set; } 
    public Foo() {} 
} 

あなたは、オブジェクト初期化子を使用した最初の例と同じ結果を得ることができ、あなたは次のコードで、工assにアクセスできることを仮定:


new Foo() { s = new SomeClass(someString) } 

ご覧のとおり、オブジェクトイニシャライザを使用すると、パブリックフィールドとパブリック(設定可能)プロパティの値を構造の作成と同時に指定することができます。ハットは、コンストラクタが特定のフィールドを初期化するオーバーロードを供給しない場合に特に便利です。 オブジェクトの初期化子は構文的な砂糖だけであり、コンパイル後はオブジェクトの初期化と実際の割り当ての順序が異なることに注意してください。

11

オブジェクトに正しく設定されていなければならないプロパティがある場合は、1つのコンストラクターを公開して、それらの必須プロパティーをパラメーターとして必要とします。

この場合、これらの必須プロパティを指定せずにオブジェクトを作成することはできません。そのようなものはオブジェクトイニシャライザによって強制できません。

オブジェクトイニシャライザは、初期割り当てを短縮するための実際の単なる構文です。ニースですが、実際には機能的にはあまり関係ありません。

マルク・

+0

建設時にオブジェクトに必須のプロパティが設定されていることを確認する別の方法は、構築されたオブジェクトを返すクラスに静的( "ファクトリ")メソッドを提供することです。そのファクトリメソッドは* private *コンストラクタを介してオブジェクトを構築します。 – DavidRR

+0

...また、1つまたは複数の他のクラスのインスタンスを構築する責任がある静的ファクトリ*クラス*を作成すると便利な場合があります(複数のプライベートコンストラクタを定義すると便利です)。たとえば、[File.Createメソッド(String)](https://docs.microsoft.com/en-us/dotnet/api/system.io.file.create?view=netframework-4.7.1#System_IO_File_Create_System_String_)を参照してください。そのオーバーロード)は 'FileStream'オブジェクトを作成します。 – DavidRR

17

あなたは

Person p = new Person { Name = "a", Age = 23 }; 

を行うと、これはオブジェクト初期化子は、本質的に何をするかです:

Person tmp = new Person(); //creates temp object calling default constructor 
tmp.Name = "a"; 
tmp.Age = 23; 
p = tmp; 

は今、これはthisのような動作を容易にします。オブジェクトイニシャライザの動作を知ることは重要です。

+0

Person p = new Person {Name = "a" }? –

+0

@ニックネームはい、非常に。これはオブジェクトイニシャライザの目的です。必要なメンバーを初期化します。 – nawfal

+2

コンストラクタparanthesisをスキップできることがわかりませんでした。ありがとう。 –

関連する問題