Разница здесь действительно тонкая и может быть оценена только в легко в IL:
class MyBuilder1
{
private MySynchronizer m_synchronizer = new MySynchronizer();
public MyBuilder1()
{
}
}
дает нам конструктор:
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2050
// Code size 18 (0x12)
.maxstack 8
IL_0000: ldarg.0
IL_0001: newobj instance void MySynchronizer::.ctor()
IL_0006: stfld class MySynchronizer MyBuilder1::m_synchronizer
IL_000b: ldarg.0
IL_000c: call instance void [mscorlib]System.Object::.ctor()
IL_0011: ret
} // end of method MyBuilder1::.ctor
где-как это:
class MyBuilder2
{
private MySynchronizer m_synchronizer;
public MyBuilder2()
{
m_synchronizer = new MySynchronizer();
}
}
дает нам:
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2063
// Code size 18 (0x12)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ldarg.0
IL_0007: newobj instance void MySynchronizer::.ctor()
IL_000c: stfld class MySynchronizer MyBuilder2::m_synchronizer
IL_0011: ret
} // end of method MyBuilder2::.ctor
Разница заключается просто в следующем:
- инициализаторы поля (
MyBuilder1
) происходит до вызов конструктора базового типа (здесь object
является базой; call instance void [mscorlib]System.Object::.ctor()
является вызовом конструктора базы) - конструкторы происходят после вызов конструктора базового типа
В большинстве случаев это не имеет значения .Если ваш базовый конструктор не вызовет виртуальный метод, который переопределяет производный тип: то будет ли поле иметь значение в переопределенном методе, будет отличаться между ними.