beforefieldinit标志有什么作用?


82

beforefieldinit标志有什么作用?当我查看班级的IL时,我看到了这个标志,但是我不知道这个标志实际上在做什么?

Answers:


132

请参阅关于此问题的文章

基本上,beforefieldinit意味着“可以在引用任何静态字段之前的任何时候初始化类型”。从理论上讲,这意味着可以非常延迟地初始化-如果您调用不涉及任何字段的静态方法,则JIT不需要初始化类型。

实际上,这意味着该类的初始化要比其他情况得多-可以在可能使用该类的第一个方法的开始处对其进行初始化是可以的。有哪些类型比较这已经beforefieldinit应用到它们,其中类型初始化到第一前刚刚发生的实际使用。

因此,假设我们有:

public static void DoSomething(bool which)
{
    if (which)
    {
        FirstType.Foo();
    }
    else
    {
        SecondType.Bar();
    }
}

如果两种类型都beforefieldinit应用了它们(在C#中,除非类型具有静态构造函数,否则它们默认情况下会执行),然后它们将在DoSomething方法开始时进行初始化(通常-不保证)。如果没有,则将根据标志beforefieldinit仅初始化其中之一

这就是为什么在实现单例模式时通常使用静态构造函数(甚至是空的构造函数!)的原因。


“可以在引用任何字段之前的任何时候初始化类型。” 运行静态方法是否也正确?
罗伊·纳米尔

CLI规范@ RoyiNamir,CLI规范指出,如果应用BeforeFieldInit,则“在首次访问为该类型定义的任何静态字段时或之前,执行该类型的初始化方法”。如果缺少该属性(静态.ctor),则“首先访问该类型的任何静态或实例字段,或者首先调用该类型的任何静态,实例或虚拟方法”。因此,除非应用了静态方法引用了另一个静态字段,否则对于应用BeforeFieldInit而言,情况并非如此。
Arman McHitarian 2013年

3
我发现使用静态构造函数(即不具有beforefieldinit标志的类)会降低性能。如果您经常调用某个类的静态成员,则似乎运行时必须在每次调用之前进行额外的检查,以测试类型是否已初始化;beforefieldinit避免了这些检查。使用beforefieldinit进行的一些基准测试大约要快50%:codeproject.com/Articles/87991/…–
Qwertie

6

看起来它将在4.6中更改

https://github.com/dotnet/coreclr/issues/1193


太棒了,这是否意味着它将等到最后一刻来初始化该字段(无论是否具有该字段beforefieldinit)?
James Ko

1
在首次使用之前,所有访问都将带有初始化检查的前缀。之后,当其他方法被绑定时,生成的代码将直接访问该字段。如果它是原始类型,那么它甚至可以用作JIT时间常数。
奥马里奥(OmariO)

2
乔恩的变化上详细分析输入初始化开始.NET 4.0在这里
RBT
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.