Monday 11 April 2011

Dot.Net: Singleton Pattern

Question:
What is a singleton?
How to implement a singleton in c#?
How do I make a singleton thread-safe?


Answer:
A singleton is a programming pattern that assures that there is only one instance of a class. (Like Highlander: "There can be only one!")

Clients are unable to create a second instance. Each time they ask the singleton provider a new instance they receive the same thing.
This pattern is useful for cases where you want a single entry point to a framework or builder class.


Simple example with with lazy initialization or instantiation.
This will initialize the Singleton only when it is used for the first time.
using System;

public class Singleton
{
   private static Singleton instance;

   private Singleton() {}

   public static Singleton Instance
   {
      get 
      {
         if (instance == null)
         {
            instance = new Singleton();
         }
         return instance;
      }
   }
}




You can initialize your instance also as a static member initialization.
The instance is created the first time any member of the class is referenced.
public sealed class Singleton
{
   private static readonly Singleton instance = new Singleton();
   
   private Singleton(){}

   public static Singleton Instance
   {
      get 
      {
         return instance; 
      }
   }
}
Notice: The class is sealed (cannot be inherited) and the instance variable is readonly.



The same thing thread-safe
using System;

public sealed class Singleton
{
   private static volatile Singleton instance;
   private static object syncRoot = new Object();

   private Singleton() {}

   public static Singleton Instance
   {
      get 
      {
         if (instance == null) 
         {
            lock (syncRoot) 
            {
               if (instance == null) 
                  instance = new Singleton();
            }
         }

         return instance;
      }
   }
}
Notice: The static field is volatile. That means any assignment to the instance variable must be completed before the instance variable can be accessed.



Here is one way to make it thread-safe and lazy.
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();
    }
}
Notice: There is a nested class, which will be initialized when you access the Instance for the first time.


The last sample is from Jon Skeet

No comments: