Jon Skeet澄清了Singleton

public sealed class Singleton { Singleton() {} public static Singleton Instance { get { return Nested.instance; } } class Nested { // Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit static Nested() {} internal static readonly Singleton instance = new Singleton(); } } 

我希望在我当前的C#应用​​程序中实现Jon Skeet的Singleton模式 。

我对代码有两个疑问

  1. 如何访问嵌套类中的外部类? 我的意思是

     internal static readonly Singleton instance = new Singleton(); 

    是什么叫封闭?

  2. 我无法理解这个评论

     // Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit 

    这个评论对我们有什么启示?

  1. 不,这与封闭无关。 嵌套类可以访问其外部类的私有成员,包括这里的私有构造函数。

  2. 在beforefieldinit阅读我的文章 。 你可能会也可能不想要没有操作的静态构造函数 – 这取决于懒惰保证你需要什么。 你应该知道,.NET 4 在一定程度上改变了实际的types初始化语义 (仍然在规范之内,但是比以前更加细化)。

真的需要这个模式吗? 你确定你不能逃避:

 public sealed class Singleton { private static readonly Singleton instance = new Singleton(); public static Singleton Instance { get { return instance; } } static Singleton() {} private Singleton() {} } 

关于问题(1):乔恩的回答是正确的,因为他隐含地将“嵌套”类私有标记为不公开或内部:-)。 你可以通过添加“private”来明确地做到这一点:

  private class Nested 

关于问题(2):基本上,有关beforeinitfield和types初始化的文章告诉你,如果没有静态构造函数,运行时可以随时初始化它(但在使用之前)。 如果你有一个静态的构造函数,你的静态构造函数中的代码可能会初始化这些字段,这意味着当你询问types时,运行时只允许初始化字段。

因此,如果您不希望运行时在使用它们之前主动初始化字段,请添加一个静态构造函数。

无论哪种方式,如果你正在实现单身你可能希望它尽可能懒惰初始化,而不是当运行时认为它应该初始化你的variables – 或者你可能只是不在乎。 从你的问题,我想你想要他们尽可能晚。

这让Jon的post相当于单身 ,这是IMO这个问题的基本主题。 哦,疑惑:-)

我想指出,他标记为“错误”的单身#3实际上是正确的(因为locking在退出时自动暗示存储器障碍 )。 当你多次使用实例(这或多或less是一个单例:-))时,它也应该比单例#2更快。 所以,如果你真的需要一个懒惰的单例实现,我可能会去那个 – 原因很简单,(1)每个人都清楚读取你的代码是怎么回事,(2)你知道会发生什么有例外。

如果你想知道:我永远不会使用单身#6,因为它可以很容易地导致死锁和意外的行为与例外。 有关详细信息,请参阅: 懒惰的locking模式 ,特别是ExecutionAndPublication。