Type initializer についてまとめ
参考資料
- ECMA-335 (4th edition)
Type initializer とは
Type initializer は CLI 仕様で規定されている、型それ自体を初期化するための特別なメソッドである*1。
要するに(C# で言うところの) static メンバの初期化子や static コンストラクタを実行してくれるアレである。
CLI 仕様書(ECMA-335)の 10.5.3 (Type initializer) 以下では、下に述べる事柄が述べられている。
Type initializer の満たすべき条件
Type initializer には以下の制約が与えられている。これらは、普通の C# コンパイラを使ってコード生成する限りは気にする必要はないだろう。
- static である
- パラメタを持たない
- 戻り値を持たない
- rtspecialname, specialname を持ち、".cctor" という名前である
Type initializer で出来ること
Type initializer では、普通のメソッドとして出来ること以外に以下の事ができる。
- initonly 属性を持つ static フィールドに書き込める
Type initializer の実行について、CLI によって保証されること
Type initializer の実行については、以下の点が守られることが、CLI 仕様によって保証されている(し、CLR*2 や mono はそれを守っている)。
共通して言えること
- type initializer の実行タイミングについて
- "all-zero" な値型や、null な参照型のメンバアクセスについてのみは、無視されうる
- つまり、null なインスタンスのメンバにアクセスした場合などは、事前に type initializer が実行されるとは限らない
- "all-zero" な値型や、null な参照型のメンバアクセスについてのみは、無視されうる
- static field はいかなるアクセスよりも前に、known state に初期化されている
- "all-zero" 値や null 値などであるということ
beforefieldinit 属性がないなら
beforefieldinit 属性でマークされているなら
- 以下の時に type initializer が実行される
- その型の static field への初回アクセス時 か それ以前
なお、beforefieldinit 属性がある場合、beforefieldinit ない場合で述べた事柄は保証されなくて良い。特に、最後の保証(type initializer の完了を待機する)が保証されないことがありうる。(ECMA-335 の 10.5.3.2 の Rationale 曰く、最後の保証は、複数 AppDomain 環境ではコストが高くつくうえ、滅多に必要がない*4ため、とのこと。)
また、この beforefieldinit の挙動は、初期化コードが特に有意な side-effect を持たない時のために用意されているそうだ(ECMA-335 8.9.5 の Note より)。