Click here to Skip to main content
Click here to Skip to main content

A Reusable Base Class for the Singleton Pattern in C#

By , 5 Apr 2013
Rate this:
Please Sign up or sign in to vote.

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).

/// <summary>
/// This class is an example of how to create a singleton based on the singleton base class.
/// </summary>
class SingletonExample : SingletonBase<SingletonExample>
{
  /// <summary>
  /// Gets or sets a string property.
  /// </summary>
  public string SomeString {get; set; }
 
  /// <summary>
  /// Initializes a new instance of the <see cref="Singleton"/> class.
  /// </summary>
  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:

/// <summary>
/// Static instance. Needs to use lambda expression
/// to construct an instance (since constructor is private).
/// </summary>
private static readonly Lazy<T> sInstance = new Lazy<T>(() => CreateInstanceOfT());

/// <summary>
/// Gets the instance of this singleton.
/// </summary>
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!

/// <summary>
/// Creates an instance of T via reflection since T's constructor is expected to be private.
/// </summary>
/// <returns></returns>
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:

/// <summary>
/// A base class for the singleton design pattern.
/// </summary>
/// <typeparam name="T">Class type of the singleton</typeparam>
public abstract class SingletonBase<T> where T : class
{
  #region Members

  /// <summary>
  /// Static instance. Needs to use lambda expression
  /// to construct an instance (since constructor is private).
  /// </summary>
  private static readonly Lazy<T> sInstance = new Lazy<T>(() => CreateInstanceOfT());

  #endregion

  #region Properties

  /// <summary>
  /// Gets the instance of this singleton.
  /// </summary>
  public static T Instance { get { return sInstance.Value; } }

  #endregion

  #region Methods

  /// <summary>
  /// Creates an instance of T via reflection since T's constructor is expected to be private.
  /// </summary>
  /// <returns></returns>
  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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Boris Brock
Software Developer
Germany Germany
No Biography provided

Comments and Discussions

 
QuestionException: PinmemberCCB201013-Nov-13 10:17 
GeneralMy vote of 5 Pinmember_Nizar19-Aug-13 2:36 
Questionfull defination of SingletonExample Pinmembershah jony22-May-13 20:51 
AnswerRe: full defination of SingletonExample PinmemberBoris Brock11-Jun-13 21:24 
GeneralMy vote of 5 PinmemberMember 84402889-Apr-13 2:21 
QuestionSingleton Pinmvpgeoyar8-Apr-13 9:20 
AnswerRe: Singleton PinmemberBoris Brock8-Apr-13 21:58 
GeneralRe: Singleton Pinmvpgeoyar9-Apr-13 8:44 
GeneralRe: Singleton Pinmemberteejay879-Apr-13 21:31 
GeneralRe: Singleton Pinmvpgeoyar10-Apr-13 10:27 
GeneralRe: Singleton Pinmemberteejay8710-Apr-13 21:17 
GeneralRe: Singleton Pinmvpgeoyar11-Apr-13 9:28 
QuestionI don't like singleton PinmemberGiuseppe Tollini5-Apr-13 8:31 
See title
Suggestionsome thoughts and missing multithreading PinmemberThomas Haller5-Apr-13 6:00 
GeneralRe: some thoughts and missing multithreading PinmemberBoris Brock7-Apr-13 21:11 
GeneralRe: some thoughts and missing multithreading Pinmemberteejay877-Apr-13 21:35 
GeneralRe: some thoughts and missing multithreading PinmemberThomas Haller7-Apr-13 23:34 
GeneralMy vote of 4 PinmemberRoberto Guerzoni4-Apr-13 6:16 
GeneralThoughts PinmemberPIEBALDconsult4-Apr-13 4:47 
GeneralRe: Thoughts PinmemberLeandro Taset4-Apr-13 6:26 
SuggestionRe: Thoughts [modified] Pinmemberteejay874-Apr-13 22:09 
GeneralRe: Thoughts PinmemberMattDavey5-Apr-13 2:04 
GeneralRe: Thoughts Pinmemberteejay875-Apr-13 2:16 
GeneralRe: Thoughts PinmemberMattDavey5-Apr-13 2:28 
GeneralRe: Thoughts Pinmemberteejay875-Apr-13 2:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web04 | 2.8.140415.2 | Last Updated 5 Apr 2013
Article Copyright 2013 by Boris Brock
Everything else Copyright © CodeProject, 1999-2014
Terms of Use
Layout: fixed | fluid