我正在研究C#的单例模式我在msdn网站上找到了这个例子.
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
private Singleton(){}
public static Singleton Instance
{
get
{
return instance;
}
}
}
Run Code Online (Sandbox Code Playgroud)
因为Singleton实例由私有静态成员变量引用,所以实例化不会发生,直到对Instance属性的调用首次引用该类.因此,此解决方案实现了lazy instantiation属性的一种形式,如Singleton的Design Patterns形式.
我不太确定何时会将内存分配给
private static readonly Singleton instance
Run Code Online (Sandbox Code Playgroud)
1)在调用Instance属性时甚至在它之前它会发生吗?
2)我需要强制类创建一个新的内存,有时清除其内容.这样做是否安全set?
set
{
instance = null;
}
Run Code Online (Sandbox Code Playgroud)
在您提供的示例代码中,将在首次访问类时创建单例实例.这意味着在第一次Instance调用时的示例.
您可以在Jon Skeet的文章"在C#中实现单例模式"中找到更多见解,请参阅方法4.
基本上,为了实现真正的懒惰行为之类的东西
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton();
static Singleton(){}
private Singleton(){}
public static Singleton Instance
{
get { return instance; }
}
}
Run Code Online (Sandbox Code Playgroud)
足够.
(但无论如何,在上述文章中可以找到完整且更好的概述.)
编辑
实际上,正如上面提到的文章所示,由于BeforeFiledInit标记,不保证在第一次访问时创建实例.你需要添加一个空的静态构造函数,这样它保证是懒惰的.否则,将在程序启动和首次访问之间的某个未指定时间创建实例.(已知.NET运行时2.0拥有更加热切的策略,因此您可能无法获得惰性行为.)
引用上述文章:
类型初始值设定项的懒惰仅在类型未标记为特殊标志时由.NET保证
beforefieldinit.不幸的是,C#编译器[...]标记了所有没有静态构造函数的类型beforefieldinit.
编辑2
如果要清理单例对象,则应将此功能包含在类Singleton本身中.
删除属性值将有效地使您的类不再是单例!想象一下,有人访问单例并获取单例实例.之后,您将属性设置为null.Singleton该类的现有对象不会消失,因为它仍然有一个参考!因此,下次访问该Instance属性时,Singleton将创建该类的另一个实例.所以你丢失了两件事:你的对象不再是单例(因为你同时存在2个实例),并且内存也没有被清除.
当加载类本身时,单例实例将被加载到内存中,这时可以调用它的方法开始执行.调用该类的实际行不必实际执行.这是一个非常小的区别,但是当静态构造函数或静态字段初始化程序可以抛出错误(这里没有)时,可能会产生难以调试的问题.
这在使用新Lazy<T>实现的.NET 4中得到修复.
http://msmvps.com/blogs/jon_skeet/archive/2010/01/26/type-initialization-changes-in-net-4-0.aspx
public sealed class Singleton
{
private static readonly Lazy<Singleton> lazy =
new Lazy<Singleton>(() => new Singleton());
public static Singleton Instance { get { return lazy.Value; } }
private Singleton()
{
}
}
Run Code Online (Sandbox Code Playgroud)
http://csharpindepth.com/Articles/General/Singleton.aspx