This article will present the necessary code to implement a generic Singleton class in C#. Singletons are implemented in code, where you
want to be sure there is one and only one instance of an object. An alternative is static classes, but static classes can only contain
static methods and static properties / fields. Often your class be a non-static class, and in some contexts it is desired to be sure there
is only one instance.
There are some help in Inversion of Control (IoC) such as MEF to create a singleton (PartCreationPolicy.Shared), but sooner or later a need
for creating a singleton is present.
Let us first review the code for the generic singleton:
public class Singleton<T> where T : new()
{
private static readonly T instance;
static Singleton()
{
instance = new T();
}
public static T Instance
{
get { return instance; }
}
private Singleton()
{
}
}
The Singleton Instance property is static and returns the private static readonly instance field of type T. It is important that the Instance property
is returning the same instance here obviously, which is why we do not have a setter on this property. We constrain the Singleton class to have the
generic constraint
new, such that we can easily instantiate the object of type T. As you can see, we do not support specifying an overloaded
constructor on the object of type T here. Without the use of the
new generic constraint, one would have to instantiation via
Activator.CreateInstance or some other means. In addition, we add a private default constructor, we do not want consumers to instantiate new Singleton objects of this class.
For a demonstration of this, let us take this sample class, with a simple derived class:
public class ProgramManager
{
private Guid guid;
public ProgramManager()
{
guid = Guid.NewGuid();
}
public void PrintGuid()
{
Console.WriteLine("Guid is:" + guid);
}
}
public class OperationManager : ProgramManager
{
}
I have created these three classes in a simple console application, this is how the running demo looks like:
var programManager = Singleton<ProgramManager>.Instance;
var secondProgramManager = Singleton<ProgramManager>.Instance;
var operationManager = Singleton<OperationManager>.Instance;
var secondOperationManager = Singleton<OperationManager>.Instance;
programManager.PrintGuid();
secondProgramManager.PrintGuid();
operationManager.PrintGuid();
secondOperationManager.PrintGuid();
Console.WriteLine("Press any key to continue ...");
Console.ReadKey();
The output is:
Guid is:842edf61-56c7-4916-a766-783e911361c8
Guid is:842edf61-56c7-4916-a766-783e911361c8
Guid is:987a113e-c664-4681-b9fb-6d463768327a
Guid is:987a113e-c664-4681-b9fb-6d463768327a
Press any key to continue ...
.
Of course, the guids above will differ for each execution of the console application, but note that we got the same Guid in both cases for the
two different classes. Our Singleton<T> Instance property always returns the same object, and keeps via the generic type argument separate
instances of the Singleton generic instance demonstrated here. This shows this generic Singleton class can be used for many different scenarios.
One feature I would like to add is the possibility to specify which constructor to call in the instantiation of the object of type T. I have not
found a correct way to implement this yet using the code above.