单例实现与静态构造函数的懒惰
Jon Skeet 在他的单例实现中建议,如果你需要单独的最大懒惰,你应该添加一个静态构造函数,这将使编译器将类型标记为beforefieldinit。
但是,我做了一些测试,如果没有 beforefieldinit,它似乎更懒。
代码示例(私有构造函数调用输出到控制台并validation字段是否已初始化:
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 在这篇文章中的答案,尝试将false传递给DoSomething() – 无论有没有静态构造函数,私有构造函数都没有被调用。
public static void DoSomething(bool which) { if (which) { var a = Singleton.Stub(); } else { Faketon.Stub(); } }
当我调用Singleton.Stub()时,私有构造函数没有被命中,当我取消注释静态ctor时,总是调用私有构造函数。
目前尚不清楚这里的价值是什么,但从根本上说,你有四个案例:
- 静态构造函数,
Singleton.Stub
调用:类型初始化程序保证运行 - 静态构造函数,
Singleton.Stub
未调用:类型初始化程序保证不运行 - 没有静态构造函数,
Singleton.Stub
调用:类型初始化程序可能会运行,但不保证 - 没有静态构造函数,
Singleton.Stub
没有被调用:类型初始化程序可能会运行,但不能保证
最后两种情况的不同之处在于,如果您将Singleton.Stub
更改为使用静态字段,则第三种情况变为“类型初始化程序保证运行”。