Jon Skeet建议in his singleton implementation如果你需要singleton的最大懒惰,你应该添加一个静态构造函数,这将使编译器将该类型标记为beforefieldinit。
然而,我做了一些测试,看起来它更懒惰没有 the 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的答案in this post尝试将false传递给DoSomething() - 无论是否使用静态构造函数,都不会调用私有构造函数。
public static void DoSomething(bool which)
{
if (which)
{
var a = Singleton.Stub();
}
else
{
Faketon.Stub();
}
}
答案 0 :(得分:5)
当我调用Singleton.Stub()时,私有构造函数没有被命中,当我取消注释静态ctor时,私有构造函数总是被调用。
目前还不清楚which
的价值在哪里,但从根本上说,你有四个案例:
Singleton.Stub
调用:类型初始化程序保证运行Singleton.Stub
未调用:类型初始化程序保证不运行Singleton.Stub
调用:类型初始化程序可能运行,但不保证Singleton.Stub
未调用:类型初始化程序可能运行,但不保证最后两种情况的不同之处在于,如果您将Singleton.Stub
更改为使用静态字段,则第三种情况将变为“类型初始化程序保证运行”。