私は最近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;
}
ドキュメント から:
コンパイラは、最初にデフォルトのインスタンスコンストラクターにアクセスしてからメンバーの初期化を処理することにより、オブジェクト初期化子を処理します。
これは、最も単純な場合(オブジェクト初期化と呼ばれる)では、基本的にデフォルトコンストラクターを呼び出してからプロパティセッターを呼び出すための略記(または構文糖)であることを意味します。匿名型の場合、この種の初期化は実際に必要であり、単なる砂糖ではありません。
あなたの質問の2番目の部分:それはスタイルの問題ですが、重要なプロパティがある場合は、デフォルト値でコンストラクタを作成しません。クライアントコードで値を明示的に設定します。また、コードの難読化コンテストに参加しているのでなければ、なぜb = A(true) {foo = false};
が良いアイデアなのか、私にはわかりません。
ただし、少し注意が必要です。
...デフォルトコンストラクターがクラスでプライベートとして宣言されている場合、パブリックアクセスを必要とするオブジェクト初期化子は失敗します。
オブジェクト初期化子は単なる構文上のシュガーであり、コンパイルされたアセンブリILでは、それらは別個のステートメントに変換され、 ILSpy でチェックします。
最初にコンストラクタが発生し、次にオブジェクト初期化子が発生します。覚えておいてください
a = new A() { foo = false };
と同じです
var temp = new A();
temp.foo = false;
a = temp;
b = new A(true) {foo = false};
実質的に以下の略です。
A temp = new A(true);
temp.foo = false;
A b = temp;
ここで、temp
は、アクセスできない変数です。コンストラクターは常に最初に実行され、続いて初期化されたプロパティが実行されます。
基本的に、ポールがすでにリンクしているもの:
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.