ローカル変数では、最適化がオンになっていると、コンパイラは(少なくとも時々) 最初に変数に代入し、次にAdd
オブジェクト初期化子の呼び出し (またはプロパティの設定) を行うコードにコンパイルします。
静的変数またはインスタンス変数を使用すると、異なる動作が見られます。
class Test
{
static List<int> StaticList = new List<int> { 1 };
List<int> InstanceList = new List<int> { 2 };
}
次の型初期化子 IL を提供します。
.method private hidebysig specialname rtspecialname static
void .cctor() cil managed
{
// Code size 21 (0x15)
.maxstack 2
.locals init (class [mscorlib]System.Collections.Generic.List`1<int32> V_0)
IL_0000: newobj instance void class [mscorlib]System.Collections.Generic.List`1<int32>::.ctor()
IL_0005: stloc.0
IL_0006: ldloc.0
IL_0007: ldc.i4.1
IL_0008: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
IL_000d: nop
IL_000e: ldloc.0
IL_000f: stsfld class [mscorlib]System.Collections.Generic.List`1<int32> Test::StaticList
IL_0014: ret
} // end of method Test::.cctor
そして、次のコンストラクター IL:
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 29 (0x1d)
.maxstack 3
.locals init (class [mscorlib]System.Collections.Generic.List`1<int32> V_0)
IL_0000: ldarg.0
IL_0001: newobj instance void class [mscorlib]System.Collections.Generic.List`1<int32>::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: ldc.i4.2
IL_0009: callvirt instance void class [mscorlib]System.Collections.Generic.List`1<int32>::Add(!0)
IL_000e: nop
IL_000f: ldloc.0
IL_0010: stfld class [mscorlib]System.Collections.Generic.List`1<int32> Test::InstanceList
IL_0015: ldarg.0
IL_0016: call instance void [mscorlib]System.Object::.ctor()
IL_001b: nop
IL_001c: ret
} // end of method Test::.ctor
どちらの場合も、フィールドが設定される前にコレクションが設定されます。メモリ モデルの問題がまだないというわけではありませんが、フィールドが空のコレクションを参照するように設定されてから呼び出しが行われるのと同じではありません。Add
割り当てスレッドの観点から、割り当てはAdd
.
一般に、オブジェクト初期化子とコレクション初期化子の式は、一時変数を使用してオブジェクトを構築することと同等です。そのため、代入で使用する場合、代入が行われる前にプロパティ セッターがすべて呼び出されます。
ただし、オブジェクト/コレクション初期化子の他のスレッドへの可視性に関して特別な保証が与えられているとは思いません。仕様に従って「手書き」で書き出すとコードがどのようになるかを想像し、そこから推論することをお勧めします。
静的初期化子とコンストラクターには保証がありますが、主に「一般的な」保証ではなく、.NET の Microsoft 実装内にあります (たとえば、C# 仕様または ECMA 仕様内)。