これは、コメントの1つで述べられているように、コーディングの好みに要約されます。次のコードをコンパイルすると
public class TestInitialization
{
private object test1 = new object();
private object test2;
public TestInitialization()
{
this.test2 = new object();
}
}
コンパイルすると、実際に使用されるコードは次のようになります。
public class TestInitialization
{
private object test1;
private object test2;
public TestInitialization()
{
this.test1 = new object();
this.test2 = new object();
}
}
全く同じものなので、好きな方を使ってください。
編集: これは、継承されたクラスと結果としてコンパイルされた IL を持つ基本クラスの例です。
基本クラス
class basetest
{
private object test1 = new object();
private object test2;
public basetest()
{
this.test2 = new object();
}
}
継承されたクラス
class testclass : basetest
{
private object testclass1 = new object();
private object testclass2;
public testclass() : base()
{
this.testclass2 = new object();
}
}
結果の IL 基本クラス
.class private auto ansi beforefieldinit basetest
extends [mscorlib]System.Object
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: newobj instance void [mscorlib]System.Object::.ctor()
L_0006: stfld object logtest.basetest::test1
L_000b: ldarg.0
L_000c: call instance void [mscorlib]System.Object::.ctor()
L_0011: nop
L_0012: nop
L_0013: ldarg.0
L_0014: newobj instance void [mscorlib]System.Object::.ctor()
L_0019: stfld object logtest.basetest::test2
L_001e: nop
L_001f: ret
}
.field private object test1
.field private object test2
}
継承クラス IL
.class private auto ansi beforefieldinit testclass
extends logtest.basetest
{
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed
{
.maxstack 8
L_0000: ldarg.0
L_0001: newobj instance void [mscorlib]System.Object::.ctor()
L_0006: stfld object logtest.testclass::testclass1
L_000b: ldarg.0
L_000c: call instance void logtest.basetest::.ctor()
L_0011: nop
L_0012: nop
L_0013: ldarg.0
L_0014: newobj instance void [mscorlib]System.Object::.ctor()
L_0019: stfld object logtest.testclass::testclass2
L_001e: nop
L_001f: ret
}
.field private object testclass1
.field private object testclass2
}
私の側に少し混乱があると思います。この例では、コンストラクターの外側のイニシャライザーは、基本コンストラクターが呼び出される直前に FIRST で初期化されます。したがって、コンストラクターの外側の初期化子は、コンストラクター内の初期化子の前に最初に初期化されますが、ほとんどの場合、これは問題になりません。技術的には、それらはすべてコンストラクター内で初期化されるように変換され、次の規則が適用されます。
- コンストラクタの外側にあるすべてのイニシャライザが最初に実行されます
- すべての基本クラスのコンストラクターが呼び出されます
- コンストラクター内のすべての初期化子が実行されます
基本的に、コンパイラはコンストラクタの外側にあるすべてのイニシャライザをコンストラクタ コードの先頭に追加し、通常どおり実行します。
したがって、この
public class test : basetest
{
private object test1 = new object();
private object test2;
public test() : base()
{
this.test2 = new object();
}
}
public class basetest
{
private object basetest1 = new object();
private object basetest2;
public basetest()
{
this.basetest2 = new object();
}
}
になる
public class test : basetest
{
private object test1;
private object test2;
public test()
{
//prepend everything first
this.test1 = new object();
//call base
base(); //not legal but just an example
//everything else that was already here
this.test2 = new object();
}
}
public class basetest
{
private object basetest1;
private object basetest2;
public basetest()
{
//prepend initializers
this.basetest1 = new object();
//if there were more base classes, the constructors would be called here
//do everything else that was already here
this.basetest2 = new object();
}
}
うまくいけば、それはより理にかなっていて、いくつかの問題を解決します。コンストラクターの「最初」または「外側」で実行されると言ったときに何人かの人々が何を意味しているのかを理解するのに問題があったことは知っています。実際にはコンストラクター内ですべて実行されますが、呼び出される順序は影響を受けます。