Introduction
Let's face it: everybody loves singletons! Over the past few years I used a lot of these little buggers throughout all my projects. Recently I became tired
of all the "copy & paste" and decided to write a reusable singleton base class for all my projects to come. Today I want to share the fruits of my work with you folks.
Background
The purpose of this base class is to reduce the coding effort when creating a new singleton to an absolute minimum. That does not only mean less finger-tiring coding work for you,
but also makes your singletons much more readable and maintainable.
This base class is also thread safe, which is an important thing when it comes to singletons.
Using the code
The code I'm presenting today consists of two classes:
SingletonBase
is the base class, that every singleton will derive from. SingletonExample
is a very simple singleton, that shows how to derive from the base class.
And that's it. All of it. Pretty simple, huh? Now let's dive right in!
The example singleton
I'll start by putting the cart before the horse.
The code below shows a very simple singleton class that derives from our magic singleton base class (which will be shown later).
class SingletonExample : SingletonBase<SingletonExample>
{
public string SomeString {get; set; }
private SingletonExample()
{
}
}
Here are the three important points to learn from the example above:
- The singleton derives from our base class
SingletonBase
. - We pass the singleton's class name as a type parameter (
SingletonBase<SingletonExample>)
). - We define a
private
constructor.
This is important since we don't want anyone to actually instantiate our singleton.
As you can see the singleton itself is super-simple. All of the heavy lifting
is done by the base class. So you can concentrate on implementing all those fancy methods and properties you have always dreamed of.
The singleton base class
Now let's get to the good stuff: our magic singleton base class! Here we want to make sure that only one instance of our singleton exists at a time. And we want to do
so in a thread safe way. Let's get there step by step:
public abstract class SingletonBase<T> where T : class
{
...
Here we declare our singleton base class. As you can see this is a template class (that's where Mr. "T" comes from).
This allows us to pass in the singleton's class as a type parameter (see the example above).
Next we have to answer an important question: how does the user
access the singleton's instance? This problem is usually solved by providing a property called "Instance
" (very creative, right?). This property returns
the one and only instance of our singleton. Here's how we implement that:
private static readonly Lazy<T> sInstance = new Lazy<T>(() => CreateInstanceOfT());
public static T Instance { get { return sInstance.Value; } }
I think the above lines of code deserve a little bit of explanation. First of all there is an static member called "sInstance
". It holds the instance of our singleton, and is lazily initialized. This is comfortably achieved by using .NET 4.0's Lazy<T>
class. And the best thing is: Lazy<T>
is fully thread safe!
The second thing to notice is the mysterious method called "CreateInstanceOfT
". Why do we need that? Why not simply call new? Well, that's due to the fact that our singleton has a private constructor (if you have forgotten, just scroll up a little bit to our SingletonExample
class). Because of this we have to resort to a little trick: the Activator!
private static T CreateInstanceOfT()
{
return Activator.CreateInstance(typeof(T), true) as T;
}
With the help of this little method we can now instantiate our singleton class, although its constructor is private. Neat, huh?
The whole singleton base class
And that's it! Now you've seen the whole singleton base class. Here's what all those bits look like put together to a complete class, ready for copy & paste:
public abstract class SingletonBase<T> where T : class
{
#region Members
private static readonly Lazy<T> sInstance = new Lazy<T>(() => CreateInstanceOfT());
#endregion
#region Properties
public static T Instance { get { return sInstance.Value; } }
#endregion
#region Methods
private static T CreateInstanceOfT()
{
return Activator.CreateInstance(typeof(T), true) as T;
}
#endregion
}
Points of Interest
As you might have noticed the Lazy<T>
class is only available in .NET 4.0 and higher. If you are somehow forced by a higher power to use .NET versions below that, this code is not for you. Sorry!
History
I've rewritten the method CreateInstanceOfT
based on the comments below. As people pointed out to me the Activator is faster than reflection when it comes to instantiating objects.