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实例= new Singleton(); 这就是所谓的终结吗? 我无法理解这一评论 //显式的静态构造函数告诉c#编译器 //不将类型标记为beforefieldinit 这个评论告诉我们什么?


不,这与闭包无关。嵌套类可以访问其外部类的私有成员,包括这里的私有构造函数。 阅读我在beforefieldinit上的文章。您可能需要也可能不需要no-op静态构造函数——这取决于惰性保证您需要什么。你应该意识到。net 4在一定程度上改变了实际的类型初始化语义(仍然在规范中,但是比以前更懒惰了)。

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

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

    static Singleton() {}
    private Singleton() {}
}

关于问题(1):Jon的答案是正确的,因为他隐式地将“Nested”类标记为私有,不使其为公共或内部:-)。你也可以通过添加'private'来明确地做到这一点:

    private class Nested

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

因此,如果你不想让运行时在你使用字段之前“主动”初始化它们,添加一个静态构造函数。

不管怎样,如果你正在实现单例,你要么希望它尽可能地延迟初始化,而不是当运行时认为它应该初始化你的变量时——或者你可能只是不在乎。从你的问题来看,我猜你希望他们越晚越好。

这就引出了Jon关于单身的帖子,在我看来,这是这个问题的潜在主题。哦,还有疑虑:-)

I'd like to point out that his singleton #3, which he marked 'wrong', is actually correct (because lock's automatically implies a memory barrier on exit). It also should be faster than singleton #2 when you use the instance more than once (which is more or less the point of a singleton :-) ). So, if you really need a lazy singleton implementation, I'd probably go for that one - for the simple reasons that (1) it's very clear for everyone that reads your code what is going on and (2) you know what will happen with exceptions.

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