バックグラウンド
Compilerが「フィールドなどの生成コードを省略する」ことを知っていint foo = 0;
ます。これは、メモリアロケータがフィールドをデフォルト値に初期化するためです。参照
class Foo
{
public int a = 1;
public int b = 0;
}
Foo..ctor:
IL_0000: ldarg.0
IL_0001: ldc.i4.1
IL_0002: stfld UserQuery+Foo.a // There is no b.
IL_0007: ldarg.0
IL_0008: call System.Object..ctor
IL_000D: ret
また、「コンパイラは.locals init
、ローカル変数を使用するすべてのメソッドを自動的に追加します。これは、メソッドの実行を開始する前に、JIT がすべてのローカル変数を初期化するコードを挿入する必要があることを示しています。」参照
質問
int foo = 0;
コンパイラがローカル変数などの IL の生成を省略しないのはなぜ.locals init
ですか? (フィールドとの一貫性のため?)
(C#仕様では、ローカル変数を確実に割り当てる必要があることを理解しています。それで問題ありません。)
(参照したリンクには、.locals init
必要な理由と、C# 仕様でローカルを初期化する必要がある理由が記載されています。ただし、デフォルト値を初期化するための追加の IL 命令が存在しなければならない理由は記載されていません。検証プロセスは.locals init
既に保証されているため)
void Main()
{
int a = 0;
int b = 1;
int c = 0;
int d = a + b + c;
d++;
}
.maxstack 2
.locals init (int a, int b, int c, int d)
IL_0000: ldc.i4.0
IL_0001: stloc.0 // a (Can be optimized away)
IL_0002: ldc.i4.1
IL_0003: stloc.1 // b
IL_0004: ldc.i4.0
IL_0005: stloc.2 // c (Can be optimized away)
IL_0006: ldloc.0 // a
IL_0007: ldloc.1 // b
IL_0008: add
IL_0009: ldloc.2 // c
IL_000A: add
IL_000B: stloc.3 // d
IL_000C: ldloc.3 // d
IL_000D: ldc.i4.1
IL_000E: add
IL_000F: stloc.3 // d