65.9K
CodeProject is changing. Read more.
Home

Incorporating Parameterized Construction in the Singleton Design Pattern

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.33/5 (2 votes)

Aug 6, 2003

3 min read

viewsIcon

75577

downloadIcon

2

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:

// .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:

// 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:

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:

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:

// 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:

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