01 Dec 2023




Intermediate

In C#, a singleton design pattern ensures that a class has only one instance and provides a global point to this instance. Here are the steps to implement the Singleton pattern in C#:

  1. Private Constructor:

    • Ensure that the class has a private constructor to prevent instantiation from outside the class.
    public class Singleton
    {
        // Private Constructor to prevent external instantiation
        private Singleton() { }
    }
    
  2. Make the class sealed: This prevents the class from being inherited, which helps to ensure that there is only one instance of the class.

    //Make the class sealed
    public sealed class Singleton
    {
        private Singleton() { }
    }
    
  3. Static Instance Property:

    • Create a private static instance of the class within the class itself.
    public sealed class Singleton
    {
        //Static Instance Property for global access
        private static Singleton instance;
        private Singleton() { }
    }
    
  4. Public Method to Access Instance:

    • Create a public method that will be used to get the instance of the class. This method should check whether an instance already exists, and if not, create one.

    Note⭐: The check for null ( if (instance == null) ) introduces a potential issue in a multithreaded environment, known as a "double-checked locking" problem. To address this, consider using a thread-safe approach.

    public sealed class Singleton
    {
        private static Singleton instance;
        private Singleton() { }
    
        public static Singleton Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new Singleton();
                }
                return instance;
            }
        }
    }
    
  5. Thread-Safe Singleton :

    • If thread safety is a concern, you might want to use a lock to ensure that only one thread can create the instance at a time. This is especially important in a multithreaded environment.
    public sealed class Singleton
    {
        private static Singleton instance;
        private static readonly object lockObject = new object();
        private Singleton() { }
    
        public static Singleton Instance
        {
            get
            {
                lock (lockObject)
                {
                    if (instance == null)
                    {
                        instance = new Singleton();
                    }
                    return instance;
                }
            }
        }
    }
    

Now, you can use the Singleton.Instance property to access the single instance of the class from anywhere in your code.

Singleton myInstance = Singleton.Instance;

This ensures that there is only one instance of the Singleton class throughout the application.

Full Code:

The Singleton design pattern ensures that a class has only one instance and provides a global point of access to that instance. Here's an example of a thread-safe Singleton implementation in C# using the double-check locking mechanism:

using System;

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

    // Private constructor to prevent instantiation outside the class.
    private Singleton()
    {
        Console.WriteLine("Singleton instance created.");
    }

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

    public void DoSomething()
    {
        Console.WriteLine("Singleton instance is doing something.");
    }
}

class Program
{
    static void Main()
    {
        // Access the Singleton instance
        Singleton singletonInstance = Singleton.Instance;
        singletonInstance.DoSomething();

        // Trying to create another instance will still return the existing instance
        Singleton anotherInstance = Singleton.Instance;
        Console.WriteLine("Are both instances the same? " + (singletonInstance == anotherInstance));

        Console.ReadLine();
    }
}

Explanation:

  1. The Singleton class has a private static instance variable and a private constructor to prevent direct instantiation.
  2. The Instance property is used to get the singleton instance. If the instance is null, it uses double-check locking to create a new instance within a synchronized block.
  3. The volatile keyword ensures that the instance variable is always read from and written to the main memory, preventing thread-local caching of the variable.
  4. The lock statement is used to ensure that only one thread at a time can create an instance of the Singleton class.

This implementation is thread-safe and ensures that only one instance of the Singleton class is created, even in a multi-threaded environment.

software-design-patterns
singleton-design-pattern