Singleton Pattern In C#

What is a Singleton Pattern?

A design pattern that restricts the instantiation of a class to only one object.

The below figure shows the static structure of this pattern. The UML class diagram is surprisingly simple because Singleton consists of a simple class that holds a reference to a single instance of itself.

Singleton provides a global, single instance by,

  • Making the class create a single instance of itself.
  • Allowing other objects to access this instance through a class method that returns a reference to the instance. A class method is globally accessible.
  • Declaring the class constructor as private so that no other object can create a new instance.

Singleton Pattern Principle

This approach ensures that only one instance is created and only when the instance is needed.

Advantages of Singleton Pattern

  • The static initialization approach is possible because the .NET Framework explicitly defines how and when static variable initialization occurs.
  • The Double-Check Locking idiom described below in "Multithreaded Singleton" is implemented correctly in the common language runtime.

Disadvantages of Singleton Pattern

  • Unit testing is far more difficult as it introduces global state into an application.
  • Reduces the potential for parallelism within a program, because access to the singleton in a multi-threaded context must be serialized, e.g., by locking.
  • Requires explicit initialization in a multithreaded application, and we have to take precautions to avoid threading issues.
  • Advocates of dependency injection would regard this as an anti-pattern, mainly due to its use of private and static methods.
  • The singleton instance is obtained using the class name. At the first view, this is an easy way to access it, but it is not very flexible. If we need to replace the Singleton class, all the references in the code should be changed accordingly.
  • Some have suggested ways to break down the singleton pattern using methods such as reflection in languages such as C#, Java etc.

Common Uses

Logger Classes

The Singleton pattern is used in the design of logger classes. To provide a global logging access point in all the application components without being necessary to create an object each time a logging operation is performed.

Configuration Classes

The Singleton pattern is used to design the classes which provide the configuration settings for an application. By implementing configuration classes as Singleton not only do we provide a global access point, but we also keep the instance we use as a cache object. When the class is instantiated (or when a value is read) the singleton will keep the values in its internal structure. If the values are read from the database or from files this avoids the reloading the values each time the configuration parameters are used.

Accessing resources in shared mode

It can be used in the design of an application that needs to work with the serial port. Let's say that there are many classes in the application, working in a multi-threading environment, which need to operate actions on the serial port. In this case, a singleton with synchronized methods could be used to manage all the operations on the serial port.

Factories implemented as Singletons

Let's assume that we design an application with a factory to generate new objects (Account, Customer, Site, Address objects) with their IDs, in a multithreading environment. If the factory is instantiated twice in 2 different threads then it is possible to have 2 overlapping IDs for 2 different objects. If we implement the Factory as a singleton we avoid this problem. Combining Abstract Factory or Factory Method and Singleton design patterns is a common practice.

  • The Abstract Factory, Builder, and Prototype patterns can use Singletons in their implementation.
  • Facade Objects are often Singletons because only one Facade object is required.
  • State objects are often Singletons.
  • Singletons are often preferred to global variables because:
  • They do not pollute the global namespace (or, in languages with namespaces, their containing namespace) with unnecessary variables.
  • They permit lazy allocation and initialization, whereas global variables in many languages will always consume resources.

There are various different ways of implementing the singleton pattern in C#. Please download the code snippet and review the different version of implementation.

Some of the references mentioned below the below video will help us to understand what is singleton pattern.
This video will help us to understand more:
  1. Why we need to use sealed keyword when creating a singleton class. 
  2. The different versions of implementations.