Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 这两个单例实现之间的差异_C#_Design Patterns - Fatal编程技术网

C# 这两个单例实现之间的差异

C# 这两个单例实现之间的差异,c#,design-patterns,C#,Design Patterns,我正在学习如何实现一些基本的设计模式。在学习Singleton模式时,我注意到web上有两种常见的实现: // Possibly from: http://www.yoda.arachsys.com/csharp/singleton.html // I cannot remember exact source, sorry :( public sealed class Singleton { // Static members are 'eagerly initialized', th

我正在学习如何实现一些基本的设计模式。在学习Singleton模式时,我注意到web上有两种常见的实现:

// Possibly from: http://www.yoda.arachsys.com/csharp/singleton.html
// I cannot remember exact source, sorry :(

public sealed class Singleton
{
    // Static members are 'eagerly initialized', that is,
    // immediately when class is loaded for the first time.
    // .NET guarantees thread safety for static initialization
    private static readonly Singleton instance = new Singleton();

    // Private constructor prevents instantiation from other classes
    private Singleton() { }

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    public static Singleton() { }

    // Get the instance of the singleton
    public static Singleton getInstance()
    {
            return instance;
    }

}
以及:

  • 在哪种情况下,您会选择热切初始化还是懒惰初始化
  • 第一个示例中的注释说初始化是线程安全的,是否正确?(我知道上面说是的,但这是互联网…)
  • 1) 这完全是一种设计选择。预先初始化或在需要时初始化

    2) 是的,它是线程安全的,因为CLR保证单线程对象初始化。(静态和实例)

    编辑


    就个人而言,在第一个示例中,我将实例字段公开,并省略getter。有兴趣知道这是否是一个坏主意吗?

    我不确定,但您似乎从这里得到了这些示例:

    如果没有,请通读一遍。对这两个版本有一些想法。 如果你问我个人:如果我需要知道单例是否已经初始化,我会选择第二种解决方案


    如果您不必处理多线程,我会使用一种更简单的方法(参见参考链接中的“坏代码”示例)。

    第一种方法是安全且懒惰的

    静态构造函数
    保证只执行一次,并且在第一次访问
    指令
    之前立即执行。如果存在静态构造函数(即使为空),则静态字段初始化保证直接在静态构造函数之前执行。如果没有静态构造函数,字段初始化可能会更早发生


    第二个是惰性的,但我不确定双锁模式是否像这样有效。我怀疑它坏了,至少在ECMA内存模型中是这样



    就我个人而言,我会避免使用任何
    类。实例
    单例模式,在大多数情况下都支持IoC单例模式。

    我肯定会支持您的第一个实现

    第二个对我来说似乎有问题。。。如果您需要/想要一个懒惰的实现,您可以使用
    lazy
    ,因为它是框架的一部分,所以感觉更舒服


    顺便说一句:有更多的方法来实现单例模式

    它是一个单体,所以我会选择选项1,除非它是一个不总是需要的巨大物体。但是我可能不会为那些通常根本不用的东西创建一个单例。

    两种实现都很好,所以这取决于您需要什么


    如果性能不是问题,请使用急切创建的第一个实例。否则,请使用第二个,其中只有第一个访问是同步的。

    可能的重复已被讨论过,并在博客上写到死。如果你使用.NET4,你可以选择使用Lazy()@henkholtman,我不这么认为。这个问题是问什么是一个好的实现,我问的是线程安全和示例用法:/WRT 1..access修饰符不允许用于静态构造函数。“。如果你问我个人:如果我需要知道单例是否已经初始化,我会选择第二个解决方案。”阅读你的链接。第二个例子在这里被列为断开。这里可能存在误解:链接文档的第二个版本=“第二个版本-简单线程安全”。但我同意,这并没有明确说明。今天早上我读了很多关于各种设计模式的东西,因为我正在用我所知道的所有语言实现它们,所以它可能来自那里。这只是我记下的两个。再次感谢您的链接:)坏代码坏是有原因的吗?为什么建议使用它?据我所知,“坏代码”指的是它不是多线程安全的。如果只有一个线程,则需要使其比所需的更复杂。从这个意义上说,我会推荐更简单/最简单的解决方案。感谢您提供的链接,看到使用
    Lazy的实现非常有趣。
    :)您每天都会学到一些东西,我对所有关于单例的对话都感到非常厌倦,但我不知道Lazy。现在我期待着下一个关于单身汉的愚蠢面试问题。Thx Yahia.第一个懒惰的人是怎样的实例只在第一次访问
    .instance
    .CodeInChaos时构造。CodeInChaos是正确的,直到我刚才检查,我还错误地认为静态是在类加载时初始化的。请原谅我是个书呆子,但你的意思是。举例来说,没有。举例。
    public class Singleton
    {
      // Static, VOLATILE variable to store single instance
      private static volatile Singleton m_instance;
    
      // Static synchronization root object, for locking
      private static object m_syncRoot = new object();
    
      // Property to retrieve the only instance of the Singleton
      public static Singleton Instance
       {
          get
          {
              // Check that the instance is null
              if (m_instance == null)
              {
                  // Lock the object
                  lock (m_syncRoot)
                  {
                      // Check to make sure its null
                      if (m_instance == null)
                      {
                          m_instance = new Singleton();
                      }
                  }
              }
    
              // Return the non-null instance of Singleton
              return m_instance;
          }
      }
    }