C# beforefieldinit标志会出现奇怪的行为和性能问题

C# beforefieldinit标志会出现奇怪的行为和性能问题,c#,clr,lazy-initialization,C#,Clr,Lazy Initialization,我试图理解beforefieldinit标志之前的。 我写了两个简单的类 class Foo { public static object o; static Foo() { o = new object(); } } class Bar { public static object o = new object(); } 然后,在Main中,我使用了这两个类,并在调用任何代码之前,将断点设置到Main方法的第一行。 在手表的窗口,我已

我试图理解beforefieldinit标志之前的。 我写了两个简单的类

class Foo
{
    public static object o;
    static Foo()
    {
        o = new object();
    }
}

class Bar
{
    public static object o = new object();
}
然后,在Main中,我使用了这两个类,并在调用任何代码之前,将断点设置到Main方法的第一行。 在手表的窗口,我已经检查并看到了

  • Foo.o是空的
  • Bar.o不是空的
  • 这有点奇怪,因为我认为该标志的目的是为了懒惰——在实际需要之前不初始化对象。 这也是关于

    这种行为的原因是什么?它会影响性能吗

    然后,我想检查性能,因此我在Main中编写了以下代码:

    Stopwatch sw = new Stopwatch();
    sw.Start();
    
    for (int i = 0; i < 2000000000; i++)
    {
        object foosObject = Foo.o;
        if (foosObject == null)
        {
            Console.WriteLine("");
        }
    }
    
    sw.Stop();
    Console.WriteLine("With Static Ctor: " + sw.Elapsed);
    sw.Reset();
    
    sw.Start();
    
    for (int i = 0; i < 2000000000; i++)
    {
        object barsObject = Bar.o;
        if (barsObject == null)
        {
            Console.WriteLine("");
        }
    }
    
    sw.Stop();
    Console.WriteLine("Without Static Ctor: " + sw.Elapsed);
    sw.Reset();
    
    Stopwatch sw=新秒表();
    sw.Start();
    对于(int i=0;i<2000000000;i++)
    {
    对象foosObject=Foo.o;
    if(foosObject==null)
    {
    控制台。写线(“”);
    }
    }
    sw.Stop();
    Console.WriteLine(“带静态Ctor:+sw.Appead”);
    sw.Reset();
    sw.Start();
    对于(int i=0;i<2000000000;i++)
    {
    对象barsObject=Bar.o;
    if(barsObject==null)
    {
    控制台。写线(“”);
    }
    }
    sw.Stop();
    Console.WriteLine(“无静态Ctor:+sw.persed”);
    sw.Reset();
    
    结果是

    带静态传感器:00:00:06.0167153

    不带静电传感器:00:00:04.2441007


    所以这是一个50%的性能差异。为什么第一个循环运行较慢?我用ILDASM检查了IL,没有发现任何差异

    看起来正常。JIT在编译Main时引用Bar时执行Bar中的cctor,以便可以假定Bar已初始化。顺便说一句,有一个更改请求可以使这个行为更加可控:@HansPassant-为什么观察Foo.o在观察Bar.o时没有调用它的静态构造函数呢?