C#中的BeforeFieldInit

来源:互联网 发布:白芨吉利知胃病中草药 编辑:程序博客网 时间:2024/06/04 19:11

今天学习设计模式中的单例模式,无意间发现了这个标志BeforeFieldInit

于是简单地搜索了一下,总结出如下内容。

The C# specification states:

The static constructor for a class executes at most once in a given application domain. The execution of a static constructor is triggered by the first of the following events to occur within an application domain:
* An instance of the class is created.
* Any of the static members of the class are referenced.

The CLI specification (ECMA 335) states in section 8.9.5:

  1. A type may have a type-initializer method, or not.
  2. A type may be specified as having a relaxed semantic for its type-initializer method (for convenience below, we call this relaxed semantic BeforeFieldInit)
  3. If marked BeforeFieldInit then the type’s initializer method is executed at, or sometime before, first access to any static field defined for that type
  4. If not marked BeforeFieldInit then that type’s initializer method is executed at (i.e., is triggered by):
    • first access to any static or instance field of that type, or
    • first invocation of any static, instance or virtual method of that type

The C# specification implies that no types with static constructors should be marked with the BeforeFieldInit flag.

换句话说,如果一个类(型)没有静态构造函数,那么它应该被标记为BeforeFieldInit。也就是说,这个类(型)的初始化工作有可能早于晚于或者就在这个类(型)的静态属性被访问时完成。

文章《What does beforefieldinit flag do?》给出的解释更简单。

Basically, BeforeFieldInit means “the type can be initialized at any point before any static fields are referenced.” In theory that means it can be very lazily initialized - if you call a static method which doesn’t touch any fields, the JIT doesn’t need to initialize the type.

下面我们来看个例子。

using System;namespace BeforeFieldInit{    class Demo    {        static Demo()        {            Console.WriteLine("Run static constructor");        }        public static string x = Print("Initialize Type");        public static string Print(string message)        {            Console.WriteLine(message);            return message;        }    }    class Program    {        static void Main(string[] args)        {            // Start            Console.WriteLine("Starting Main");            // Invoke a static method on Test            Demo.Print("Call print function.");            Console.WriteLine("After calling Print.");            // Reference a static field in Test            string y = Demo.x;            Console.WriteLine("After accessing field.");        }    }}

运行后得到的结果如下:

Starting Main
Initialize Type
Run static constructor
Call print function.
After calling Print.
After accessing field.

把静态构造函数注释掉,运行后得到的结果如下:

Initialize Type
Starting Main
Call print function.
After calling Print.
After accessing field.

我们发现在main函数里,我们还没有访问Demo类,Demo类的静态变量的初始化工作就已经完成了。这就是前面提到的早于的意思。理论上晚于或者就在也应该可以发生的,只是我没有重现出来。

References

C# and beforefieldinit
What does beforefieldinit flag do?

原创粉丝点击