私はこのようなクラスを書くのに慣れています:
public class foo {
private string mBar = "bar";
public string Bar {
get { return mBar; }
set { mBar = value; }
}
//... other methods, no constructor ...
}
Barを自動プロパティに変換するのは便利で簡潔に思えますが、コンストラクタを追加して初期化を行わずに初期化を保持するにはどうすればよいですか?
public class foo2theRevengeOfFoo {
//private string mBar = "bar";
public string Bar { get; set; }
//... other methods, no constructor ...
//behavior has changed.
}
コンストラクターの追加は、自動プロパティから得られるはずの労力の節約とは一致しないことがわかります。
このようなものは私にとってより理にかなっています:
public string Bar { get; set; } = "bar";
更新-以下の回答は、C#6が登場する前に書かれました。 C#6では、次のように記述できます。
public class Foo
{
public string Bar { get; set; } = "bar";
}
also読み取り専用の自動実装プロパティを書き込むことができます。これらのプロパティはコンストラクタでのみ書き込み可能です(ただし、デフォルトの初期値を指定することもできます:
public class Foo
{
public string Bar { get; }
public Foo(string bar)
{
Bar = bar;
}
}
今のところこれを行う方法がないのは残念です。コンストラクターで値を設定する必要があります。 (コンストラクターチェーンを使用すると、重複を避けることができます。)
自動的に実装されたプロパティは現在便利ですが、確かにより良いものになる可能性があります。コンストラクターでのみ設定でき、読み取り専用フィールドによってサポートされる読み取り専用の自動実装プロパティほど頻繁にこの種の初期化を望んでいません。
これは、C#5までは発生していませんでしたが、C#6で計画されています-宣言の時点で初期化を許可するという点でand読み取り専用の自動実装プロパティを許可するコンストラクター本体で初期化されます。
クラスのコンストラクタを介してそれを行うことができます:
public class foo {
public foo(){
Bar = "bar";
}
public string Bar {get;set;}
}
別のコンストラクター(つまり、パラメーターを取るコンストラクター)または多くのコンストラクターがある場合は、常にこれを使用できます(コンストラクターチェーンと呼ばれます)。
public class foo {
private foo(){
Bar = "bar";
Baz = "baz";
}
public foo(int something) : this(){
//do specialized initialization here
Baz = string.Format("{0}Baz", something);
}
public string Bar {get; set;}
public string Baz {get; set;}
}
常にデフォルトコンストラクターへの呼び出しをチェーンする場合、そこにすべてのデフォルトプロパティの初期化を設定できます。連鎖する場合、呼び出しコンストラクターの前に連鎖コンストラクターが呼び出されるため、より特殊なコンストラクターは、必要に応じて異なるデフォルトを設定できます。
C#6.0で可能になります。
public int Y { get; } = 2;
デフォルトのコンストラクター(およびもちろん必要な場合はデフォルト以外のコンストラクター):
public foo() {
Bar = "bar";
}
これはとにかく舞台裏で起こることなので、これは私が信じている元のコードより劣らないパフォーマンスです。