Singleton Design Pattern In C#

Introduction

A singleton design pattern is all about ensuring that a class has only one instance in the application. It is a design pattern from the Creational Pattern of Gang of Four (GOF) Design Patterns.

In this pattern, we have to restrict creating the instance if it is already created and use the existing one.

First of all, we have to make our class constructor private so that we can not create objects from outside of the class using the new keyword.

We have many approaches to use singleton design patterns in C#. Here, we are going through a few of them.

Let’s start with the example for better understanding.

We are using a console application for this example, and we are going to take the Employee class and use a private constructor.

Example

public class Employee
{
    private static Employee instance = null;
    private Employee() { }
    public static Employee GetInstance
    {
        get
        {
            if (instance == null)
            {
                instance = new Employee();
            }
            return instance;
        }
    }
}

In the code given above, we are using a static property named Instance for getting the instance outside of the class without using its object; and inside this property, we are checking if the instance is already created or not. If it is first-time request, then we are creating an instance. We can also use a method instead of a property as below.

public static Employee GetInstance()
{
    if (instance == null)
    {
        instance = new Employee();
    }
    return instance;
}

So now, the Employee class has only one constructor, which is private, so we can’t create an instance using a new keyword outside of the class

C#

And also, we can’t inherit this class into another class because of a private constructor.

private constructor

Now, we can use the instance property many times and will check the instances are the same or not as below.

static void Main(string[] args)
{
    Employee emp1 = Employee.GetInstance;
    Employee emp2 = Employee.GetInstance;
    if (emp1 == emp2)
    {
        Console.WriteLine("Same instances");
    }
    else
    {
        Console.WriteLine("Different instances");
    }
    Console.ReadLine();
}

Output

C#

The first approach is good, but it is not thread-safe. Let's assume that the first time two different threads will evaluate the if condition at the same time to check if the instance is null or not, and for both cases, it will return true because, till now, no instance has been created. So, both threads will enter into the if condition and create new instances. It is a violation of the singleton design pattern.

To overcome this situation, we have to write threads safety program as below.

Example 2 

public class Employee
{
    private static Employee instance = null;
    private static readonly object instanceLock = new object();
    private Employee() { }
    public static Employee GetInstance
    {
        get
        {
            lock (instanceLock)
            {
                if (instance == null)
                {
                    instance = new Employee();
                }
                return instance;
            }
        }
    }
}

This approach is thread-safe because, at one time, only one thread can enter inside the lock block. Multiple threads can not access GetInstance at the same time which means it is a slow approach.

To overcome this situation, we have to write a double-check locking program as below.

Example 3

public class Employee
{
    private static Employee instance = null;
    private static readonly object instanceLock = new object();
    private Employee() { }
    public static Employee GetInstance
    {
        get
        {
            if (instance == null)
            {
                lock (instanceLock)
                {
                    if (instance == null)
                    {
                        instance = new Employee();
                    }
                }
            }
            return instance;
        }
    }
}

In this approach, firstly, we check if (instance == null ) every time after creating an instance of the class first time. So, from the second time onwards, it will not go inside of the first if block and return the existing instance, but in the case of the very first time, suppose two threads will come at the same time to access the first if statement and get the true value and enter into the if block, then also, only one thread can enter into the lock statement and wait for other thread to complete the task.

So, after completion of the task of the first thread, when the second thread enters inside the lock block, it will check again if(instance==null); and at this time, we already have an instance which is created by the first thread, so it will not allow inside the second if block and will return existing instance.

We are going to see the same thing without using if condition or lock in our next approach.

Example 4

public class Employee
{
    private static readonly Employee instance = new Employee();
    private Employee() { }
    public static Employee GetInstance
    {
        get
        {
            return instance;
        }
    }
}

This is the very simple and thread-safe approach. It is called Static initialization or Early instance creation. Singleton Design pattern is very useful for the logger implementation in our application and this is the famous design pattern.

In this article, we have covered the basic understanding of the Singleton design pattern.


Similar Articles