Introduction
This article is yet another explanation and implementation of singleton pattern. We will look at what singleton pattern is and how to implement it in C#. This is no way the best and recommended way of implementing singleton pattern in C#. The main idea for this article is just to present the concept of singleton pattern to the reader.
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 have to worry about managing the single instance.
- This single instance class should be accessible by the complete system or say by most part of the system.
- This single instance subsystem should not be created and initialized unless it is required (lazy initialization).
Now let us see how we can have a class that will let the callers create only one single instance of it. To do that, the first thing we should ask ourselves is how instance of the classes are created. The answer to this question 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 access to the constructor, i.e., make the constructor private
.
Now 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
method will not need callers to have an instance to be called) inside the class, i.e., GetInstance
which will create an object of this class and return it to the applications.
Using the Code
Let us now 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
{
private Singleton()
{
}
private static Singleton instance = null;
public static Singleton GetInstance()
{
if (instance == null)
{
instance = new Singleton();
}
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 only be accessed by only a single thread at any given time. So let's do that and introduce a lock in our class to guard the GetInstance
calls.
public sealed class Singleton
{
private Singleton()
{
}
private static Singleton instance = null;
private static readonly object _lock = new object();
public static Singleton GetInstance()
{
lock (_lock)
{
if (instance == null)
{
instance = new Singleton();
}
return instance;
}
}
}
Now the instance retrieval code can only be accessed by one single thread at any given time. But 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 that we have 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. So 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
{
private Singleton()
{
}
private static Singleton instance = null;
private static readonly object _lock = new object();
public static Singleton GetInstance()
{
if (instance == null)
{
lock (_lock)
{
if (instance == null)
{
instance = new Singleton();
}
}
}
return instance;
}
}
Now what we have is a class that will acquire lock
only for first instance creation and 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 that we could 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 GetInstance
method) or the first instance of the class is created (which is not a valid scenario here as constructor is private
). So let's look at the implementation with the following changes:
public sealed class Singleton
{
private Singleton()
{
}
private static readonly Singleton instance = null;
static Singleton()
{
instance = new Singleton();
}
public static Singleton GetInstance()
{
return instance;
}
}
So what we have done here is that we have 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 by the GetInstance
method.
The instance
field has been marked as readonly
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 lock
s.
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<T>
<t>. 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 Single Responsibility Principle and should revisit our class design again.
Point of Interest
Although this stuff is very basic and is repeatedly covered by many texts. You will find the code snippets in all the singleton implementations also 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 the guys who are just at the starting with this pattern. For more advanced readers, I recommend reading this blog for much more detailed explanation of this pattern: C# in Depth: Implementing the Singleton Pattern[^]
History
- 20th January, 2016 - undeleted - Someone might benefit from the explanation
- 2013 - Deleted - similar implementation/code exists in all singleton documentation
- 2012 - First version