单身人士由Jon Skeet澄清

amu*_*tha 212 .net c# architecture singleton design-patterns

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();
    }
}
Run Code Online (Sandbox Code Playgroud)

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

我对代码有两个疑问

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

    internal static readonly Singleton instance = new Singleton();
    
    Run Code Online (Sandbox Code Playgroud)

    有什么叫封闭吗?

  2. 我无法理解这个评论

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    
    Run Code Online (Sandbox Code Playgroud)

    这个评论暗示了什么?

Jon*_*eet 356

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

  2. 阅读我在beforefieldinit上的文章.您可能想要也可能不想要无操作静态构造函数 - 这取决于您需要什么样的懒惰.您应该知道.NET 4 在某种程度上改变了实际的类型初始化语义(仍然在规范内,但比以前更懒).

真的需要这种模式吗?你确定你无法逃脱:

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

    static Singleton() {}
    private Singleton() {}
}
Run Code Online (Sandbox Code Playgroud)

  • @Anindya:不,没关系.您可能想要邮寄JetBrains来抱怨:) (11认同)
  • @Moons:你没有.单身人士在AppDomain的持续时间内生活. (3认同)
  • `FieldBeforeInit`是来自`Microsoft`的`MahaBharata` (3认同)
  • @JonSkeet,我刚刚向JetBrains提出了这个问题(#RSRP-274373).让我们看看他们能想出什么.:) (2认同)
  • @JonSkeet任何不使用`Lazy <T>`的理由,这样你就不必为魔术`BeforeFieldInit`副作用声明一个静态构造函数? (2认同)

atl*_*ste 49

关于问题(1):Jon的答案是正确的,因为他隐含地将"嵌套"类标记为不公开或内部:-).你可以通过添加'private'来明确地做到这一点:

    private class Nested
Run Code Online (Sandbox Code Playgroud)

关于问题(2):基本上关于beforeinitfield类型初始化的帖子告诉你的是,如果你没有静态构造函数,运行时可以随时初始化它(但在你使用它之前).如果您确实有静态构造函数,则静态构造函数中的代码可能会初始化字段,这意味着只有在您请求类型时才允许运行时初始化字段.

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

无论哪种方式,如果您正在实现单例,您要么将其初始化为尽可能延迟,而不是在运行时认为它应该初始化您的变量时 - 或者您可能只是不关心.从你的问题我想你想尽可能晚.

这带来了Jon关于单身人士的帖子,这是IMO这个问题的基本话题.哦和疑惑:-)

我想指出他标记为'错误'的单身#3实际上是正确的(因为锁定会自动暗示退出时的内存屏障).当你多次使用实例时,它也应该比单身#2更快(这或多或少是一个单身的点:-)).所以,如果你真的需要一个懒惰的单例实现,我可能会选择那个 - 原因很简单:(1)每个读取代码的人都很清楚,(2)你知道会发生什么有例外.

如果您想知道:我永远不会使用单例#6,因为它很容易导致死锁和异常的意外行为.有关详细信息,请参阅:lazy的锁定模式,特别是ExecutionAndPublication.

  • 尝试回答有关Jon Skeet已经回答的Jon Skeet问题的额外分数. (71认同)
  • `关于问题(1):Jon的答案是正确的......`Jon Skeet**总是**正确.... (62认同)
  • @valdetero哈哈哈.这......哈哈哈+1 (8认同)