单例实现懒惰与静态构造函数

Jon Skeet在他的单例实现中建议,如果你需要单例的最大懒惰,你应该添加一个静态构造函数,它将使编译器将类型标记为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;
        }
    }
}

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

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

在我试图理解beforefieldinit会有什么区别的时候,我也读过Skeet在这篇文章中的回答,尝试了将DoSomething()传递给false的方法 - 无论是否使用静态构造函数,都不会调用私有构造函数。

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

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

目前还不清楚which的价值,但基本上你有四种情况:

  • 静态构造函数, Singleton.Stub调用:类型初始化器保证运行
  • 静态构造函数Singleton.Stub不被调用:类型初始化器保证不运行
  • 没有静态构造函数, Singleton.Stub调用:类型初始值设定项可能会运行,但不能保证
  • 没有静态构造函数, Singleton.Stub未被调用:类型初始值设定项可能会运行,但不能保证
  • 最后两种情况只有不同之处在于,如果您将Singleton.Stub更改为使用静态字段,则第三种情况会变成“类型初始值设定项保证运行”。

    链接地址: http://www.djcxy.com/p/51103.html

    上一篇: Singleton implementation laziness with static constructor

    下一篇: Why singleton class should be sealed?