C# Singleton DesignPattern

Singleton
 
Before moving to the Singleton Design Pattern, let's first understand what a singleton is.
 
Singleton allows creating only one object to a class and this class restricted to one instance provides a global point of access to it.
 
Advantages
 
The advantages of a Singleton Pattern are,
  1. It supports lazy loading.
  2. Support of Static Initialization.
  3. It has a single point of access to a particular instance and it is very easy to maintain.
Disadvantages
 
This pattern does not support parallelism within a program because there is no multi-threaded system access in the singleton pattern and an object must be serialized by locking.
 
Singleton class vs. Static methods
 
The following points compare the Singleton class vs. Static methods,
  1. A Static Class cannot be extendable whereas a singleton class can be extended.
  2. A Static Class is able to instantiate but a singleton class prevents it.
  3. Singleton supports STATE initialization whereas Static Class not.
  4. When program or namespace containing the class is loaded, the static class is loaded automatically by the CLR. 
Implementation of the singleton design pattern class
 
The following code is for a thread-safe implementation of the singleton pattern.
 
Implementation of the Singleton Design Pattern
 
First version - not thread-safe,
  1. // Bad code! Do not use!  
  2. using System;  
  3. using System.Collections.Generic;  
  4. using System.Linq;  
  5. using System.Text;  
  6. using System.Threading.Tasks;  
  7. namespace ConsoleApplication {  
  8.     publicsealedclass SingletonClass {  
  9.         //Self instance of the class  
  10.         privatestatic SingletonClass _instanceSingleton = null;  
  11.         //Private constructor to restrict class inhertiance   
  12.         private SingletonClass() {}  
  13.         publicstatic SingletonClassInstance {  
  14.             get {  
  15.                 if (_instanceSingleton == null) {  
  16.                     _instanceSingleton = new SingletonClass();  
  17.                 }  
  18.                 return _instanceSingleton;  
  19.             }  
  20.         }  
  21.     }  
This is not thread-safe. Becuase it voilates the singleton pattern when two different threads could both have evaluated the test if (_instanceSingleton==null) and found it to be true, then both create instances.Factually the instance may be created already before the expression is evaluated, but the memory model doesn't guarantee that the new value of instance other threads can see unless suitable memory pass.

Thread-safety using double-check locking

Singleton Class
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Threading.Tasks;  
  6. namespace ConsoleApplication {  
  7.     public sealed class SingletonClass: IDisposable {  
  8.         private static volatile SingletonClass _instanceSingleton = null;  
  9.         private static readonly Object _tryLock = new object();  
  10.         public int counter = 0;  
  11.         private SingletonClass() {}  
  12.         public static SingletonClass singletonClass {  
  13.             get {  
  14.                 if (_instanceSingleton != nullreturn _instanceSingleton;  
  15.                 lock(_tryLock) {  
  16.                     if (_instanceSingleton == null) {  
  17.                         _instanceSingleton = new SingletonClass();  
  18.                     }  
  19.                     return _instanceSingleton;  
  20.                 }  
  21.             }  
  22.         }  
  23.         public void writeSignature() {  
  24.             Console.WriteLine("Singleton function {0}", counter);  
  25.             this.Dispose();  
  26.         }  
  27.         public void Dispose() {  
  28.             GC.SuppressFinalize(this);  
  29.         }  
  30.     }  
  31. }  
Main Program Class
 
Test the implemention of the Singleton Class in Main Program Class,
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Threading.Tasks;  
  6. namespace ConsoleApp1 {  
  7.     public class Program {  
  8.         private staticvolatile Program _progInstance;  
  9.         public static Program progInstance {  
  10.             get {  
  11.                 if (_progInstance == null) _progInstance = new Program();  
  12.                 return _progInstance;  
  13.             }  
  14.         }  
  15.         public void run() {  
  16.             //Create the first singleton instance  
  17.             SingletonClass singClassTwo = SingletonClass.singletonClass;  
  18.             //Create the second singleton instance  
  19.             SingletonClass singClass = SingletonClass.singletonClass;  
  20.             //invoke the method with singleton desing pattern  
  21.             singClassTwo.writeSignature();  
  22.             singClassTwo.counter++;  
  23.             //invoke the function with singleton desing pattern  
  24.             singClass.writeSignature();  
  25.             singClass.counter++;  
  26.             Console.Read();  
  27.         }  
  28.         static void Main(string[] args) {  
  29.             progInstance.run();  
  30.         }  
  31.     }  
  32. }  
Next Recommended Reading Creating Lazy<T> - Singleton Class