假设我们有一个类A带有beforefieldinit修饰符(beforefieldinit修饰符是编译器在编译完之后,自动加上的,只能通过反编译工具看)。总的来说,加上beforefieldinit修饰符就意味着“类A会在变量可能被引用的前一刻,提前完成初始化。从理论上,加上beforefieldinit修饰符的类A可能延迟初始化,如果你调用的静态方法没有引用任何静态类变量,JIT就不需要初始化这个类A。
实际上,类A也可能早早地初始化,即使我们在代码中没有引用到类A中的变量。但这也没什么问题,他可以在可能用到类变量的第一个方法就初始化。打个比方,就好像我们办酒席,我们不可能确认具体有多少人回到,我们只能预先安排多少要多少桌子,多少菜(这就是提前初始化的概念)。比较一下代码段,代码段中的两个类FirstType、SecondType都没有加beforefieldinit修饰符,则那个类先被初始化取决于which变量。
1 public static void DoSomething(bool which) 2 { 3 if (which) 4 { 5 FirstType.Foo(); 6 } 7 else 8 { 9 SecondType.Bar(); 10 } 11 }
如果这两个类FirstType、SecondType都有加beforefieldinit修饰符(在C#中默认会加上,除非这个类型实现了静态构造函数),在刚进入DoSomething这个方法的时候,这两个类就会同时被初始化(通常是这样,不能绝对保证),跟which变量无关了。
这也是为什么我们建议在单例模式中使用静态构造函数的原因。
本文翻译自http://stackoverflow.com/questions/610818/what-does-beforefieldinit-flag-do