在单例模式中,我们有一个私有构造函数和一个公共静态方法,如下所示 -
public class MyClass
{
private static MyClass _uniqueInstance;
private MyClass()
{
}
public static MyClass GetInstance()
{
if(_uniqueInstance==null)
{
_uniqueInstance = new MyClass();
}
return _uniqueInstance;
}
}
每当我们需要这个类的对象时,我们可以通过调用静态方法来创建此类的一个且只有一个实例 -
var myObject = MyClass.GetInstance();
但我很困惑为什么我们在GetInstance()方法中检查null,因为“_ uniqueInstance”已经是一个静态变量,因此它将被初始化并仅分配一次内存。即使我们不检查null并仍然使用“new”初始化对象,也不会再为此对象分配内存,因为它是静态变量。那么,这个空检查的用途是什么? 请清除我的怀疑。
答案 0 :(得分:3)
如果您使用以下代码:
public static MyClass GetInstance()
{
_uniqueInstance = new MyClass();
return _uniqueInstance;
}
然后,每当有人调用此GetInstance
时,您将得到一个与Singleton相矛盾的类的不同实例。 Singleton模式的想法是始终获得类的相同实例,无论您在应用程序中调用它多少次。这个实例应该只构造一次。
所以基本上,只有第一次调用GetInstance
以便实例化私有静态字段(默认为null)时,null检查才会返回true,并且在后续调用中将返回相同的实例。
请记住,您在此处显示的此单例模式实现不是线程安全的。如果2个线程同时在开头调用GetInstance
方法,则可能会获得2个不同的实例。
您可以在this article
中阅读有关Singleton模式和各种C#实现的更多信息。
答案 1 :(得分:2)
我感觉到初始化者,工厂和单身人士之间的混淆。
字段初始值设定项:
static readonly object Value = new object();
工厂方法:
static object CreateValue()
{
return new object();
}
单身模式:
static object _value;
static object Value
{
get
{
return _value ?? (_value = new object());
}
}
初始化程序在编译时被移除到static constructor,它会像您猜测的那样运行一次。除了顺序之外,静态字段的初始化是不可控制的。当任何静态字段初始化时,则初始化所有静态字段。单例模式可以防止这种情况。
工厂方法旨在作为instance constructor的抽象。
单例模式可以被视为字段初始值设定项的抽象,确保在必要时不引入资源。但是,对于最明确引用的资源,例如String.Empty
,更明智的做法是使用静态字段来避免混乱。
答案 2 :(得分:1)
我们使用Singleton模式只获取一个对象的实例,并在任何地方使用此实例。
如果我们删除空检查if(_uniqueInstance==null)
,则每次调用GetInstance
时,都会创建一个新实例,并将其存储在_uniqueInstance
变量中。
即使我们不检查null并仍然使用初始化对象 “new”,不会再为这个对象分配内存,因为它是一个 静态变量。
内存仅作为引用类型分配给_uniqueInstance
,因为它是静态的。但您可以为此静态变量分配许多引用,并且可以根据需要在内存中创建这些对象。
那么,这个空检查的用途是什么
空检查确保_uniqueInstance
仅使用MyClass
实例分配一次,并且永远不会在应用程序域的生命周期内更改。因此,每次调用GetInstance
都会获得MyClass
的相同实例。
答案 3 :(得分:0)
这是错误的:
即使我们不检查null并仍然使用初始化对象 “new”,不会再为这个对象分配内存,因为它是一个 静态变量。
调用new
将分配新内存,_uniqueInstance
将有一个新指针。因此,每次调用方法时都会有不同的实例 - 它不是单例。