Singleton实现与静态构造函数的懒惰

Bor*_*ode 5 c# singleton static-constructor

乔恩斯基特建议在他的单身执行,如果你需要为你的最大的懒惰单身,你应该添加静态构造函数,这将使编译器标记类型beforefieldinit.

但是,我做了一些测试,如果没有 beforefieldinit ,它似乎更懒.

代码示例(私有构造函数调用输出到控制台并验证字段是否已初始化:

public sealed class Singleton
{
    private static readonly Singleton instance = new Singleton();

    public static string Stub()
    {
        return "123";
    }

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    //static Singleton()
    //{
    //}
    private Singleton()
    {
        Console.WriteLine("private ctor");
    }

    public static Singleton Instance
    {
        get
        {
            return instance;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当我调用Singleton.Stub()时,私有构造函数没有被命中,当我取消注释静态构造函数时,总是调用私有构造函数.

这是我可以跟踪静态构造函数的唯一区别.

在我尝试理解beforefieldinit之间的区别时,我也读过Skeet 在这篇文章中的答案,尝试将false传递给DoSomething() - 无论是否有静态构造函数,私有构造函数都没有被调用.

public static void DoSomething(bool which)
{
    if (which)
    {
        var a = Singleton.Stub();
    }
    else
    {
        Faketon.Stub();
    }
}
Run Code Online (Sandbox Code Playgroud)

Jon*_*eet 5

当我调用Singleton.Stub()时,私有构造函数没有被命中,当我取消注释静态ctor时,总是调用私有构造函数.

目前还不清楚which这里的价值是什么,但从根本上说,你有四个案例:

  • 静态构造函数,Singleton.Stub名为:type initializer,保证运行
  • 静态构造函数,Singleton.Stub未调用:类型初始化程序保证不运行
  • 没有静态构造函数,Singleton.Stub称为:类型初始化程序可能会运行,但不保证
  • 没有静态构造函数,Singleton.Stub没有调用:类型初始化程序可能会运行,但不保证

最后两种情况的不同之处在于,如果更改Singleton.Stub为使用静态字段,则第三种情况变为"类型初始化程序保证运行".