我一直在想静态字段
/ 构造函数
的问题。
静态类
在第一次引用其字段时进行初始化,这很简单。
但是CLR如何知道这是第一次呢?
我一直在想静态字段
/ 构造函数
的问题。
静态类
在第一次引用其字段时进行初始化,这很简单。
但是CLR如何知道这是第一次呢?
当一个静态类的字段被引用时,该类会在第一次初始化,这很容易理解。
但实际上情况并不那么简单。如果忽略方法调用,除非被标记为beforefieldinit
,否则静态类必须在其字段首次访问之前进行初始化。如果被标记为beforefieldinit
,则可以提前进行初始化。 (Jon Skeet在他的文章中有更多关于beforefieldinit
的信息。)
这如何影响类初始化的检查?由于CLR使用JIT编译,因此它在JIT编译方法时检查类初始化。如果该类被标记为beforefieldinit
且尚未初始化,则JIT编译器立即对其进行初始化。然后它实际上编译方法,在其中可以假设类已经被初始化,因此无需进行任何检查。
如果没有beforefieldinit
,如果类尚未初始化,则JIT编译器必须发出代码以在每个潜在的第一次字段访问之前检查初始化。但是,如果类已经初始化并且正在JIT编译另一个方法,则JIT编译器不再需要在那里发出检查。
这可能会对性能产生负面影响。从上述内容可以清楚地看出,为了防止这种情况发生,您需要确保将有问题的类标记为beforefieldinit
。而从C#实现这一点的方法是不要使用static
构造函数,仅使用static
字段初始化程序。