web-dev-qa-db-ja.com

C#のコンストラクターとオブジェクト初期化子の優先順位

私は最近C#でオブジェクト初期化子を学習していましたが、コンストラクタと競合する場合にどのように動作するのか疑問に思っています。

public class A
{
    public bool foo { get; set; }
    public A()
    {
        foo = true;
    }
    public A(bool bar)
    {
        foo = bar;
    }
}

これを試すとどうなりますか?

public class B
{
    a = A() {foo = false};
    b = A(true) {foo = false};
}

コンストラクターのデフォルトは、trueで始まり変更可能なboolを持つ良い方法ですか?

public A(bar=true)
{
    foo = bar;
}
51
bbill

ドキュメント から:

コンパイラは、最初にデフォルトのインスタンスコンストラクターにアクセスしてからメンバーの初期化を処理することにより、オブジェクト初期化子を処理します。

これは、最も単純な場合(オブジェクト初期化と呼ばれる)では、基本的にデフォルトコンストラクターを呼び出してからプロパティセッターを呼び出すための略記(または構文糖)であることを意味します。匿名型の場合、この種の初期化は実際に必要であり、単なる砂糖ではありません。

あなたの質問の2番目の部分:それはスタイルの問題ですが、重要なプロパティがある場合は、デフォルト値でコンストラクタを作成しません。クライアントコードで値を明示的に設定します。また、コードの難読化コンテストに参加しているのでなければ、なぜb = A(true) {foo = false};が良いアイデアなのか、私にはわかりません。

ただし、少し注意が必要です。

...デフォルトコンストラクターがクラスでプライベートとして宣言されている場合、パブリックアクセスを必要とするオブジェクト初期化子は失敗します。

44
Paul Sasik

オブジェクト初期化子は単なる構文上のシュガーであり、コンパイルされたアセンブリILでは、それらは別個のステートメントに変換され、 ILSpy でチェックします。

enter image description here

35

最初にコンストラクタが発生し、次にオブジェクト初期化子が発生します。覚えておいてください

a = new A() { foo = false };

と同じです

var temp = new A();
temp.foo = false;
a = temp;
16
juharr
b = new A(true) {foo = false};

実質的に以下の略です。

A temp = new A(true);
temp.foo = false;
A b = temp;

ここで、tempは、アクセスできない変数です。コンストラクターは常に最初に実行され、続いて初期化されたプロパティが実行されます。

11
Lee

基本的に、ポールがすでにリンクしているもの:

C#5言語仕様 (7.6.10.1)から

Processing of an object creation expression that includes an object initializer or
collection initializer consists of first processing the instance constructor and then
processing the member or element initializations specified by the object initializer or
collection initializer.
4
Chris