web-dev-qa-db-ja.com

オブジェクト初期化子とコンストラクターの違いは何ですか?

この2つの違いは何ですか?また、「コンストラクター」に対して「オブジェクト初期化子」を使用するのはいつですか?それが重要な場合は、C#で作業しています。また、オブジェクト初期化メソッドはC#または.NETに固有ですか?

159
Pete

オブジェクト初期化子は、オブジェクトを使用しているときにオブジェクトの構築を簡素化するために、C#3に追加されたものです。

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

MyObject myObjectInstance = new MyObject(param1, param2);

この場合、MyObjectのコンストラクターは、値param1およびparam2を使用して実行されます。これらは両方とも、メモリに新しいMyObjectを作成するために使用されます。作成されたオブジェクト(これらのパラメーターを使用してセットアップされる)が返され、myObjectInstanceに設定されます。

一般に、無効な状態でオブジェクトを作成できないように、コンストラクターがオブジェクトを完全にセットアップするために必要なパラメーターを要求することは良い習慣と考えられています。

ただし、多くの場合、「追加」プロパティを設定できますが、必須ではありません。これは、オーバーロードされたコンストラクターで処理できますが、大部分の状況で必ずしも有用ではない多くのコンストラクターを持つことにつながります。

これにより、オブジェクト初期化子が生成されます-オブジェクト初期化子を使用すると、オブジェクトのプロパティまたはフィールドを設定できますafter構築されましたが、before他の方法で使用できます。例えば:

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

これは、これを行う場合とほぼ同じように動作します。

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

ただし、multi-threaded環境では、オブジェクトが完全に初期化されていない状態になるのを防ぐため、オブジェクト初期化子の原子性は有益な場合があります( この答え を参照してください)-nullであるか、意図したとおりに初期化されています。

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

225
Reed Copsey

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

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

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

44
JaredPar

するとき

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 のような動作が容易になります。オブジェクト初期化子がどのように機能するかを知ることは重要です。

27
nawfal

オブジェクトが適切に機能するために設定する必要があるプロパティがある場合、1つの方法は、これらの必須プロパティをパラメーターとして必要とする単一のコンストラクターを公開することです。

その場合、これらの必須プロパティを指定せずにオブジェクトを作成することはできません。そのような何かは、オブジェクト初期化子によって強制することはできません。

オブジェクト初期化子は、実際には、初期割り当てを短縮するための単なる「構文の便利さ」です。いいですが、実際にはあまり機能的ではありません。

マーク

14
marc_s

コンストラクターは、(おそらく)パラメーターを受け入れ、クラスの新しいインスタンスを返すメソッドです。初期化ロジックが含まれている場合があります。以下に、コンストラクターの例を示します。


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

次の例を考えてみましょう。


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

次のコードでSomeClassにアクセスできると仮定すると、オブジェクト初期化子を使用して最初の例と同じ結果を得ることができます。


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

ご覧のとおり、オブジェクト初期化子を使用すると、パブリックフィールドとパブリック(設定可能)プロパティの値を、構築の実行と同時に指定できます。これは、コンストラクターが特定のフィールドを初期化するオーバーロードを提供しない場合に特に役立ちます。ただし、オブジェクト初期化子は単なる構文上のシュガーであり、コンパイル後も割り当てのシーケンスと実際には変わらないことに注意してください。

4
em70