Singleton Design Pattern in C#

Singleton Design Pattern in C# with an Example

In this article, I will discuss the Singleton Design Pattern in C# with Examples. Please read our previous article discussing Shallow Copy and Deep Copy in C# with Examples. The Singleton Design Pattern in C# falls under the Creational Pattern Category. It belongs to the creational pattern category, dealing with object creation and manipulation. As part of this article, we will discuss the following pointers.

  1. What is Singleton Design Pattern?
  2. What are the Advantages of using the Singleton Design Pattern?
  3. Implementation Guidelines of Singleton Pattern in C#.
  4. Example of the Singleton Pattern using C#.
  5. When to use Singleton Design Pattern.
  6. What are the Advantages and Disadvantages of using the Singleton Design Pattern in C#?
What is Singleton Pattern in C#?

The Singleton pattern is a design pattern that restricts the instantiation of a class to one object and provides a way to access its object. This is useful when exactly one object is needed to coordinate actions across the system. That means we need to use the Singleton Design Pattern in C# to ensure that only one instance of a particular class will be created and provide simple global access to that instance for the entire application.

Singleton Design Pattern in C#

As you can see in the above diagram, different clients (Client A, Client B, and Client C) are trying to get the singleton instance. Once the client gets the singleton instance, they can invoke the methods (Method 1, Method 2, and Method n) using the same instance. If this is confusing, don’t worry; we will discuss it with practice. 

Implementation Guidelines of Singleton Design Pattern in C#:

The following are the guidelines to implement the Singleton Design Pattern in C#.

  1. We need to declare a constructor that should be private and parameterless. This is required because it will restrict the class from being instantiated from outside the class. It only instantiates from within the class.
  2. The class should be declared sealed, ensuring it cannot be inherited. This is going to be useful when you are dealing with the nested class. We will discuss this scenario with an example in our next article.
  3. We must create a private static variable referencing the class’s singleton instance.
  4. We also need to create a public static property/method that will return the singleton instance of the class. This method or property first checks whether an instance of the singleton class is created. If the singleton instance is created, it returns that instance; otherwise, it will create an instance and then return it.
Example of Singleton Design Pattern using C#

Let us understand the Singleton Design pattern in C# with Examples. We can implement the Singleton Design Pattern in C# in many ways. They are as follows. We will discuss all the following methods to implement the Singleton Design Pattern in C#.

  1. No Thread-Safe Singleton Design Pattern in C#
  2. Thread-Safety Singleton Implementation using Lock.
  3. Implementing Thread-Safety Singleton Design Pattern using Double-Check Locking.
  4. Using Eager Loading to Implement Thread-Safety Singleton Design Pattern
  5. Using Lazy<T> Generic Class to Implement Lazy Loading in Singleton Design Pattern.
No Thread-Safe Singleton Design Pattern Implementation in C#

This article will discuss the No Thread-Safe Singleton Design Pattern implementation in C#. The rest of the implementations will be discussed individually in our upcoming articles. Let us understand how to implement the No Thread Safe Singleton Design Pattern in C# with an Example. First, create a class file, Singleton.cs, and then copy and paste the following code. 

using System;
namespace SingletonDemo
{
    public sealed class Singleton
    {
        //This variable value will be increment by 1 each time the object of the class is created
        private static int Counter = 0;

        //This variable is going to store the Singleton Instance
        private static Singleton Instance = null;

        //The following Static Method is going to return the Singleton Instance
        public static Singleton GetInstance()
        {
            //If the variable instance is null, then create the Singleton instance 
            //else return the already created singleton instance
            //This version is not thread safe
            if (Instance == null)
            {
                Instance = new Singleton();
            }

            //Return the Singleton Instance
            return Instance;
        }

        //Constructor is Private means, from outside the class we cannot create an instance of this class
        private Singleton()
        {
            //Each Time the Constructor called, increment the Counter value by 1
            Counter++;
            Console.WriteLine("Counter Value " + Counter.ToString());
        }

        //The following can be accesed from outside of the class by using the Singleton Instance
        public void PrintDetails(string message)
        {
            Console.WriteLine(message);
        }
    }
}

Here, we created the Singleton class as sealed, which ensures that the class cannot be inherited from the derived classes. The class is created with a private parameterless constructor, ensuring that the class will not be instantiated from outside the class. But we can create instances within the same class. Again, we declared the instance variable private and initialized it with the null value, ensuring that only one class instance will be created based on the null condition. The public method, GetInstance, returns only one instance of the class by checking the value of the private variable instance. The public method PrintDetails can be invoked from outside the class through the singleton instance.

We are done with our first version of the singleton design pattern implementation, which is not thread-safe. Let us see how we can use the above Singleton class in our Main method of Program class. So, modify the Main method of the Program class as follows. As you can see in the code below, we are calling the GetInstance() static method of the Singleton class, which will return the Singleton instance, and then, using that Singleton instance, we are calling the PrintDetails. And we are doing this two times.

using System;
namespace SingletonDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            //Call the GetInstance static method to get the Singleton Instance
            Singleton fromTeachaer = Singleton.GetInstance();
            fromTeachaer.PrintDetails("From Teacher");

            //Call the GetInstance static method to get the Singleton Instance
            Singleton fromStudent = Singleton.GetInstance();
            fromStudent.PrintDetails("From Student");

            Console.ReadLine();
        }
    }
}

Run the application, and it will give you the following output.

Singleton Design Pattern in C#

As you can see in the above output, it clearly shows that the private constructor is executed only once, even though we have called the GetInstance method twice and printed the counter value as 1. Hence, it proves that the singleton instance is created only once. The way we implement the singleton design pattern in the above example is not to be thread-safe. It means in a multithreaded environment, it can create multiple instances of the singleton class. We will discuss making the singleton class thread-safe in our Thread-Safe Singleton Design Pattern article. 

What are the Advantages of using the Singleton Pattern in C#?

The Advantages of using the Singleton Design Pattern in C# are as follows.

  1. The first and most important advantage of using the singleton design pattern in C# is that it takes care of concurrent access to the shared resource. That means if we share a resource with multiple clients simultaneously, then concurrent access to that resource is well managed by the singleton design pattern.
  2. It can be lazy-loaded and also has Static Initialization.
  3. To share common data, i.e., master and configuration data, which is not frequently changed in an application. In that case, we need to cache the objects in memory.
  4. It is easy to maintain as it provides a single global access point to a particular instance.
  5. To reduce the overhead of instantiating a heavy object again and again.
What are the Disadvantages of using the Singleton Design Pattern in C#?

The disadvantages of using the Singleton Design Pattern in C# are as follows:

  1. Unit testing is very difficult because it introduces a global state into an application.
  2. It reduces the potential for parallelism within a program because to access the singleton instance in a multi-threaded environment, and you need to serialize the object using locking.
When to Use Singleton Design Pattern in C#?

Here are situations where employing the Singleton pattern in C# might be appropriate:

Managing Shared Resources: Singleton is suitable for managing shared resources, such as:

  • A database connection pool.
  • A file manager that handles all file operations.
  • A cache where multiple parts of an application need to store and retrieve objects.

Configuration Settings: A Singleton can store and access configuration settings for an application-wide configuration object that needs to be accessed from multiple places.

Logging: A Singleton logger class can be used to log messages throughout the application. Since logging typically involves writing to a single resource (like a file or console), using a Singleton makes sense to avoid conflicts and ensure consistency.

Hardware Interface Access: When interfacing with hardware resources like printers or serial ports, a Singleton can ensure coordinated access, preventing conflicts arising from multiple access points.

Performance Considerations: Creating an instance of some classes can be resource-intensive. If such instances are used frequently, creating and reusing them once is more efficient, making Singleton a good choice.

When Not to Use Singleton Design Pattern in C#?

However, it’s equally important to recognize when not to use the Singleton pattern:

  • Testing Challenges: Singletons can make unit testing difficult since they carry state across tests. This state persistence can lead to tests that are not independent, making it hard to isolate issues.
  • Global State Management: Singleton introduces a global state in your application, which can lead to hidden dependencies between classes, making the system more complex and less predictable.
  • Concurrency Issues: Singletons can introduce concurrency and synchronization issues in multithreaded applications, particularly if the Singleton state is mutable.
  • Scalability and Flexibility Limitations: Singletons can limit scalability and flexibility. They often become bottlenecks as the application grows, and changing the Singleton implementation can be challenging due to its global impact.
  • Overuse and Misuse: Singleton is often overused by developers looking for a simple way to ensure only one instance of a class without understanding the implications. Its misuse can lead to design problems that become evident only later in development.
Real-Time Scenarios where we use the Singleton Design Pattern in C#:

Here are some real-time scenarios where the Singleton design pattern can be beneficial in C#:

  • Configuration Management: Singletons are often used to manage configuration settings for an application. Since configuration settings typically remain constant throughout the application’s lifecycle and are accessed from many different places, a Singleton ensures that all parts of the application have a consistent view of these settings.
  • Logging: A common use case for Singletons is in logging frameworks. A Singleton logger ensures that log entries are centralized and consistently formatted, regardless of which part of the application generates them. It also manages access to the log file, preventing conflicts and ensuring thread safety.
  • Database Connections: Managing database connections via a Singleton can effectively ensure that the application uses a shared, consistently configured connection pool. This approach can improve performance and prevent the overhead of frequently opening and closing connections.
  • Hardware Interface Communication: For applications that interact with hardware devices like printers, cameras, or barcode scanners, a Singleton can provide a centralized management point for all interactions with the hardware. This ensures coordinated access and avoids conflicts or duplication of effort.
  • Caching: Singletons are useful for caching, where data that’s expensive to obtain (like results of complex database queries) is stored and reused. A Singleton cache ensures that the cached data is globally accessible and consistent across the application.
  • Application Services: Services that provide application-wide functionality, such as a licensing service or a task scheduler, can be implemented as Singletons. This ensures a single point of control and coordination for these services.
  • State Management: A Singleton can be used to manage this state in some applications, particularly those with a complex state that needs to be shared and consistently maintained (such as in certain types of game development).

In the next article, I will discuss Why we Need to use the Sealed Keyword in the Singleton Class, as we already have a private constructor. In this article, I explain the basic concepts of the Singleton Design Pattern in C# with Examples. I hope you understand why we need the Singleton Design Pattern in C# with Examples.

11 thoughts on “Singleton Design Pattern in C#”

  1. Using “Get” in property names is not a good idea (and doesn’t meet the .NET naming standards).
    You basically end up with a method called get_GetInstance !
    Just call it “Instance” (or “SingleInstance” if you prefer).
    Alternatively, you could make it a method: public SingleInstance GetInstance() …

Leave a Reply

Your email address will not be published. Required fields are marked *