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。
我对代码有两个疑问
如何访问嵌套类中的外部类?我的意思是内部静态只读 Singleton instance = new Singleton();有什么叫做闭包吗?我无法理解这条评论 // 显式静态构造函数告诉 C# 编译器 // 不要将类型标记为 beforefieldinit 这个评论对我们有什么建议?
不,这与闭包无关。嵌套类可以访问其外部类的私有成员,包括此处的私有构造函数。阅读我关于 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() {}
}
关于问题(1):乔恩的回答是正确的,因为他通过不公开或内部的方式将“嵌套”类隐式标记为私有:-)。您也可以通过添加“私人”来明确地做到这一点:
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。
Regarding question (1): The answer from Jon is correct ...
Jon Skeet总是正确....
不定期副业成功案例分享
Lazy<T>
以便您不必为神奇的BeforeFieldInit
副作用声明静态构造函数?FieldBeforeInit
是来自Microsoft
的MahaBharata