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's Singleton pattern。
我对代码有两个疑问
如何访问嵌套类中的外部类?我的意思是
internal static readonly Singleton instance = new Singleton();
有什么叫封闭吗?
我无法理解此评论
// Explicit static constructor to tell C# compiler
// not to mark type as beforefieldinit
这条评论暗示了什么?
答案 0 :(得分:352)
不,这与闭包无关。嵌套类可以访问其外部类的私有成员,包括私有构造函数。
阅读我的article on beforefieldinit。您可能想要也可能不想要无操作静态构造函数 - 这取决于您需要什么样的懒惰。您应该知道.NET 4 changes the actual type initialization semantics somewhat(仍在规范范围内,但比以前更懒)。
你确实需要这种模式吗?你确定你无法逃脱:
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
public static Singleton Instance { get { return instance; } }
static Singleton() {}
private Singleton() {}
}
答案 1 :(得分:48)
关于问题(1):Jon的答案是正确的,因为他隐含地将“嵌套”类标记为不公开或内部:-)。你可以通过添加'private'明确地做到这一点:
private class Nested
关于问题(2):基本上the post about beforeinitfield和type initialization告诉你的是,如果你没有静态构造函数,运行时可以随时初始化它(但在你使用它之前)。如果你有静态构造函数,静态构造函数中的代码可能会初始化字段,这意味着只有在你要求输入类型时才允许运行时初始化字段。
因此,如果您不希望运行时在使用之前“主动”初始化字段,请添加静态构造函数。
无论哪种方式,如果您正在实现单例,您要么将它初始化为尽可能延迟,而不是在运行时认为它应该初始化变量时 - 或者您可能只是不关心。从你的问题我想你想尽可能晚。
这带来了Jon关于singleton的帖子,这是IMO这个问题的基本主题。哦,怀疑: - )
我想指出他标记为“错误”的单身#3实际上是正确的(因为锁定是自动implies a memory barrier on exit)。当你多次使用实例时,它也应该比单身#2更快(这或多或少是一个单身的点:-))。所以,如果你真的需要一个懒惰的单例实现,我可能会选择那个 - 原因很简单:(1)每个读取代码的人都很清楚,(2)你知道会发生什么有例外。
如果你想知道:我永远不会使用单身#6,因为它很容易导致死锁和异常的意外行为。有关详细信息,请参阅:lazy's locking mode,特别是ExecutionAndPublication。