Click here to Skip to main content
15,886,639 members
Articles / Programming Languages / C#
Article

Incorporating Parameterized Construction in the Singleton Design Pattern

Rate me:
Please Sign up or sign in to vote.
2.33/5 (2 votes)
5 Aug 20033 min read 74.4K   15   9
How to incorporate parameterized construction in Microsoft's recommended implementation of a Singleton

Introduction

Many articles have been written about the Singleton design pattern and there have been a few on how to implement it in .NET. This article is not intended to be a restatement of those. Instead I want to describe a solution to a problem that occurred to me soon after reading Microsoft's recommended implementation of the Singleton pattern in .NET. The Microsoft solution was published in February 2002, titled Exploring the Singleton Design Pattern. Here it is:

C#
// .NET Singleton
sealed class Singleton 
{
  private Singleton() {}
  public static readonly Singleton Instance = new Singleton();
}

The traditional solution, as originally elaborated in Java, uses a technique called "double-check locking" in order to address thread safety. When translated to C# it looks like this:

C#
// Double-Check Lock Singleton  
class Singleton 
{
  public static Singleton Instance() 
  {
    if (_instance == null) 
    {
      lock (typeof(Singleton)) 
      {
        if (_instance == null) 
        {
          _instance = new Singleton();
        }
      }
    }
    return _instance;      
  }
  protected Singleton() {}
  private static volatile Singleton _instance = null;
}

For a full discussion and explanation of the issues, and the above two solutions, please refer to the Microsoft article. Needless to say, Microsoft's recommended solution is far simpler than the traditional solution. But a problem occurred to me...

The Problem

What happens if I want to perform initialization of the singleton at construction time? Well, in the traditional solution I can just overload the

Instance()
method to take parameters and this will delegate to an overloaded protected constructor. So, for example, if I have a single WebMaster object, I can write:

C#
WebMaster webMaster = WebMaster.Instance("Kevin", "McFarlane");

However, with the recommended solution I can't do this. Instance is a read-only field, not a method, so I can't parameterize it. I'd been thinking about this on and off for some time before I came up with a reasonable solution. But I would be interested in seeing alternative solutions.

At first I thought that the only way to do this was to make two separate calls along the following lines:

C#
WebMaster webMaster = WebMaster.Instance;
webMaster.Create("Kevin", "McFarlane");

But this kind of thing is never ideal for a client. It's always preferable to have an object fully constructed at creation time. Or, if this is not possible, and further initialization needs to be done, this should be hidden from the client. Well, in the end, we can't really do this but we can improve matters. And the solution was virtually staring me in the face in the Microsoft example showing how to apply the recommended solution. Essentially we just arrange things so that the two separate calls can be combined into one. So, at least it looks like we're doing parameterized construction. Here's how:

C#
// Singleton with "parameterised constructor"
sealed class WebMaster
{
  public static readonly WebMaster Instance = new WebMaster();

  public WebMaster Create(string firstName, string lastName)
  {
    _firstName = firstName;
    _lastName = lastName;
    
    return Instance;
  }

  public string FirstName
  {
    get
    {
      return _firstName;
    }
  }

  public string LastName
  {
    get
    {
      return _lastName;
    }
  }

  private WebMaster() {}
  private string _firstName;
  private string _lastName;
}

The Create method serves as a "parameterized constructor." We can now write code such as the following, which is more concise:

C#
// Create a fully-constructed WebMaster instance
WebMaster webMaster = WebMaster.Instance.Create("Kevin", "McFarlane");

// Check its contents
Console.WriteLine("First Name = " + webMaster.FirstName);
Console.WriteLine("Last Name = " + webMaster.LastName);

Further Issues

If we wish to prevent multiple initialization through calling Create more than once we can just add an internal flag to indicate whether the instance has been "created" or not and raise an exception if it has.

But what if we wish to have only parameterized construction? That is, what if we want to guarantee at compile time that the instance is created in an initialized state? For example, suppose all instances of WebMaster must have their name properties set. I can't see a way of doing this other than by documentation. We can do better at runtime.

We could make every public routine, such as LastName, check a flag and then raise an exception if WebMaster hasn't been initialized. This is something that can be done using conditionally compilable precondition checking that we might disable for a release build.

Alternatively, if WebMaster hasn't been initialized the fields will be null. So when a client tries to use the name properties it will soon notice that they haven't been set.

The latter approach is cleaner and simpler. We don't have to do anything. The former approach means more work but it has the advantage that the specification is made explicit and verifiable in code.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United Kingdom United Kingdom
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralSimpler with global variables Pin
DFlatCSharp17-Feb-06 4:58
DFlatCSharp17-Feb-06 4:58 
GeneralInitializing the singleton Pin
mwl17-Aug-03 23:02
mwl17-Aug-03 23:02 
GeneralA third way?:) Pin
Stoyan Damov17-Aug-03 17:33
Stoyan Damov17-Aug-03 17:33 
GeneralNot the best pattern to use Pin
deepeddie13-Aug-03 2:48
deepeddie13-Aug-03 2:48 
GeneralHolding instances to a Singleton Pin
Anonymous12-Aug-03 21:18
Anonymous12-Aug-03 21:18 
GeneralRe: Holding instances to a Singleton Pin
Kevin McFarlane13-Aug-03 0:25
Kevin McFarlane13-Aug-03 0:25 
GeneralRe: Holding instances to a Singleton Pin
david laribee13-Aug-03 3:17
david laribee13-Aug-03 3:17 
GeneralRe: Identity Map Pattern Pin
Kevin McFarlane13-Aug-03 5:43
Kevin McFarlane13-Aug-03 5:43 
GeneralRe: Identity Map Pattern Pin
david laribee14-Aug-03 2:23
david laribee14-Aug-03 2:23 

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

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