The Singleton Pattern in C#: An Absolute Beginner’s Tutorial
This article is yet another explanation and implementation of the singleton pattern. We will look at what is singleton pattern is and how to implement it in C#. This is no way the best and recommended way of implementing the singleton pattern in C#, but this article is intended to present the concept of singleton pattern to readers.
Join the DZone community and get the full member experience.
Join For FreeThis article is yet another explanation and implementation of the singleton pattern. We will look at what is singleton pattern is and how to implement it in C#. This is no way the best and recommended way of implementing the singleton pattern in C#, but this article is intended to present the concept of singleton pattern to readers.
Background
Whenever we have a scenario in our application where:
- A single instance of a class is required in the application and the class itself is able to enforce the single instance on itself. The rest of the system need not worry about managing the single instance.
- This single instance class should be accessible by the complete system or most parts of the system.
- This single instance subsystem should not be created and initialized unless it is required. (lazy initialization)
Let's see how we can have a class that will let the callers create only one single instance of it. The first thing we should ask ourselves is how are the instance of the classes created. The answer is by calling new for the class which in turn will call the constructor of the class. So, if we want the applications not to be able to create by number of instances, we should first restrict the access to the constructor (i.e. make the constructor private).
If we are making the constructor private, the next question we have is how will we be creating the instance of this class. Since the private constructor can still be called from the class itself, we can create an instance of this class inside the class itself. So, to do this we need to create a static method (static methods will not need callers to have an instance to be called) inside the class (i.e. GetInstancewhich will create an object of this class and return it to the applications).
Using the Code
Let's look at the class that is implementing the instance creation using the above discussed method and returning the instance to the caller.
public sealed class Singleton
{
// A private constructor to restrict the object creation from outside
private Singleton()
{
}
// A private static instance of the same class
private static Singleton instance = null;
public static Singleton GetInstance()
{
// create the instance only if the instance is null
if (instance == null)
{
instance = new Singleton();
}
// Otherwise return the already existing instance
return instance;
}
}
Now the above class will let the user create only one instance of this class i.e. singleton in the simplest of forms.
Hello Multi-Threading
There is a problem with this class: it is not thread safe. So to make it thread safe, we need to make sure that the instantiation code can be accessed only by a single thread at any given time. So, lets do that and introduce a lock in our class to guard the GetInstancecalls.
public sealed class Singleton
{
// A private constructor to restrict the object creation from outside
private Singleton()
{
}
// A private static instance of the same class
private static Singleton instance = null;
private static readonly object _lock = new object();
public static Singleton GetInstance()
{
lock (_lock)
{
// create the instance only if the instance is null
if (instance == null)
{
instance = new Singleton();
}
// Otherwise return the already existing instance
return instance;
}
}
}
Now the instance retrieval code can only be accessed by one single thread at any given time. Bu,t this incorporates a performance problem. Our idea was to not let multiple threads be able to create multiple instances, so we needed to guard the instance creation part in lock. What we have done instead is guarded the complete method with lock, which would mean that the lock will be acquired even when the instance has been created and it just needs to be returned. To circumvent this problem, we need to guard only the instance creation part under lock and not the instance return part.
public sealed class Singleton
{
// A private constructor to restrict the object creation from outside
private Singleton()
{
}
// A private static instance of the same class
private static Singleton instance = null;
private static readonly object _lock = new object();
public static Singleton GetInstance()
{
if (instance == null)
{
lock (_lock)
{
// create the instance only if the instance is null
if (instance == null)
{
instance = new Singleton();
}
}
}
// Otherwise return the already existing instance
return instance;
}
}
Now what we have is a class that will acquire lock only for the first instance creation and the rest of the time it will return the already created instance.
Using the .NET CLR Capabilities for Thread Safety
When we are using C#, we can utilize the CLR behaviour to have a thread safe implementation without the complexity of locking. What we could do is include a static constructor in the class that will take care of the instance creation. The static constructor of a class is called when either the first static member of the class is accessed (in our case it will be GetInstancemethod) or the first instance of the class is created (which is not a valid scenario here as constructor is private). Look at the implementation with the following changes.
public sealed class Singleton
{
// A private constructor to restrict the object creation from outside
private Singleton()
{
}
// A private static instance of the same class
private static readonly Singleton instance = null;
static Singleton()
{
// create the instance only if the instance is null
instance = new Singleton();
}
public static Singleton GetInstance()
{
// return the already existing instance
return instance;
}
}
Here we moved the instantiation in the static constructor which will get called when the GetInstance method will be called. Static constructor will create the instance and that instance will get returned from by the GetInstance method.
The instance field has been marked as read-only so that it can only be instantiated during static initialization. And, now we have a fairly usable singleton class that is thread safe without the performance overhead of locks.
Note: One might argue that in our last version the initialization is not lazy, as if this class has any other static member then the instance will get created even if it is not requested. There is one more version of singleton possible where this can be circumvented using either nested class or Lazy. But I am not going to discuss them here. In most cases a singleton will not have other static methods. If we find ourselves in a scenario where we have a singleton that also has other static methods, perhaps we are violating the Single Responsibility Principle and should revisit our class design again.
Point of Interest
You will find the code snippets in all the singleton implementations the same as there are not many possible implementations of this pattern with C#. Still, I thought it could really be useful to put an explanation of the pattern in my own words for those who are just starting with this pattern. For more advanced readers, I recommend reading this blog for a much more detailed explanation of this pattern: C# in Depth: Implementing the Singleton Pattern[^].
Published at DZone with permission of Rahul Rajat Singh, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments