在Singleton模式中使用null检查有什么用?

时间:2015-12-13 08:38:09

标签: c# design-patterns singleton

在单例模式中,我们有一个私有构造函数和一个公共静态方法,如下所示 -

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”初始化对象,也不会再为此对象分配内存,因为它是静态变量。那么,这个空检查的用途是什么? 请清除我的怀疑。

4 个答案:

答案 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的相同实例。

Read more about singleton

答案 3 :(得分:0)

这是错误的:

  

即使我们不检查null并仍然使用初始化对象   “new”,不会再为这个对象分配内存,因为它是一个   静态变量。

调用new将分配新内存,_uniqueInstance将有一个新指针。因此,每次调用方法时都会有不同的实例 - 它不是单例。