Mon, Feb 13 2006 12:28 PM Marc Jacobi

Singleton Generics [updated]

The Singleton pattern is probably the most famous pattern of all. Usually it is implemented as a behaviour of a specific class. But why not let the developer decide how to manage instance lifetimes? The new .NET 2.0 Generics feature gives us just the tools for creating these object lifetime classes.

public static class StaticInstance<T>
    where T : new()
{
    private static T _instance;
    private static object _lock = new object();

    public static T Current
    {
        get
        {
            if (_instance == null)
            {
               lock (_lock)
               {
                   if (_instance == null)
                   {
                       _instance = new T();
                   }
               }
            }

            return _instance;
        }
    }
}

This code manages one instance of Type T in a (AppDomain) static variable, your typical Singleton implementation. Any class can be used as a Singleton now, just call StaticInstance<MyClass>.Current to access the instance of your type 'MyClass'. Beware though that being a Singleton instance has concurrency issues in that multiple threads could access that one instance of your class at the same time.

In an ASP.NET context you often have the need to have "static" information available but private to the current request. Well, simply write another instance manager class such as this one:

public static class HttpContextInstance<T>
     where T : new()
{
     private static string _typeName = typeof(T).FullName;

     public static T Current
     {
          get
          {
              Debug.Assert(HttpContext.Current != null);

              T instance = (T)HttpContext.Current.Items[_typeName];

              if (instance == null)
              {
                  instance = new T();
                  HttpContext.Current.Items[_typeName] = instance;
              }

              return instance;
          }
    }

    public static void Dispose()
    {
        IDisposable instance = HttpContext.Current.Items[_typeName] as IDisposable;

        if (instance != null)
        {
            instance.Dispose();
        }

        HttpContext.Current.Items[_typeName] = null;
    }
}

The instance is stored in the Items collection of the HttpContext, thus making the instance private to just the current web request. I've also included a Dispose method to dispose of the instance's resources when the request is done (global.asax) and clear the slot in the HttpContext items collection. You could think of other implementations for storing instances in the Thread Local Storage, the logical CallContext or any other place that might be convienient to you.

Have fun,
Marc Jacobi

 



[UPDATE 14-feb-06]

 

I like to point out some of the problems that you may encounter using this approach. The following issues should be taken into account:

  1. A Type specified for T must be able to cope with the concurrency consequences of the instance class implementation. For the StaticInstance example this means that it should syncronize access to its member variables.
  2. The Type (T) must have a public default constructor and your team could use that default constructor to create their own instances. For some types this is not a real big issue for others it can introduce hard-to-track-down bugs. If your Type (T) is not designed to be instantiated more than once implement your own Current property and remove your (default) constructor(s).
  3. All team members should "know" what Type (T) is accessed by which instance class. If one member uses StaticInstance<MyClass>.Current and another uses HttpContextInstance<MyClass>.Current you'll have 2 instances living two different lifetimes. This is a weakness that can be overcome and we will discuss next.

Because C# (generics) does not support the typedef keyword (C++: allows defining a new type using other types declaratively) the only way to simplify and hardwire a generics type is to derive from it. So if you use the following code template for instance class implementations you can fix issue 3 by deriving a new type.

public class StaticInstance<T>
    where T : new()
{
    private StaticInstance()
    {}

    public static T Current
    {
        get
        {
            // [your implementation here]
        }
    }
}

Now, say you use a static instance of MyClass in your application you can derive a new type to hardwire the T parameter. This also gives you one point of definition for the MyClass-singleton and makes it easy to transparently change the instance class backing up the singleton.

public class MyClassSingleton : StaticInstance<MyClass>
{}

I hope this update gives you a better overview of the consequenses of using this approach.
Keep the questions and suggestions coming.

Greetings,
Marc Jacobi

# re: Singleton Generics

Monday, February 13, 2006 4:56 AM by Karijn Wessing

Very good,

only one little thing.
all books about pattrens use 'Instance' in stead of 'Current'

Greetings,

Karijn Wessing

# re: Singleton Generics

Monday, February 13, 2006 5:23 AM by Obiwan Jacobi

Yes, I know. The .NET library uses Current and I personally think that Current is a better name than Instance. Instance is more implementation-related while Current just says "here's the current instance". When you're trying to explain a pattern I would prefer Instance, in production code I would prefer Current.

# re: Singleton Generics

Monday, February 13, 2006 6:23 AM by Ramon

I don't think your singleton class is thread safe in all environments. Especially on the current cpu generations.

Make your singleton instance volatile or use another singleton pattern.

Although it is very unlikely that a race condition will occur.. It could in theory :)

# re: Singleton Generics

Monday, February 13, 2006 6:38 AM by Obiwan Jacobi

... and thats whats so cool about this approach: If you see a bug, you fix it for all your singletons! ;-)

# re: Singleton Generics

Monday, February 13, 2006 12:40 PM by Erwyn van der Meer

This is very useful. I have handcoded a lot a these things for (ASP).NET 1.1. I will definitely use something like this for future .NET 2.0 applications where generics are available.

@Ramon. The singleton construct used by Marc is thread-safe without a volatile modifier in the Microsoft .NET 2.0 memory model (but not in the ECMA memory model): see http://msdn.microsoft.com/msdnmag/issues/05/10/MemoryModels/default.aspx.

# re: Singleton Generics

Tuesday, February 14, 2006 12:44 AM by Ramon Smits

@Erwyn: Thanks for the link. I'll read it when I have the time. So this is different from the behaviour in .NET 1.x. Didn't knew that had changed this. Makes like a bit easier on these issues.

# re: Singleton Generics [updated]

Tuesday, March 07, 2006 5:00 PM by Federico Lois

I have been working with this problem too and found a tradeoff for it. Comments are welcomed.

# re: Singleton Generics [updated]

Sunday, August 20, 2006 1:31 PM by Remco Kapinga [Macaw]

Here's a detailed description on creating a thread safe singleton class, without using locks (!).

http://www.yoda.arachsys.com/csharp/singleton.html

Any change of mixing that with your generic approach?

# re: Singleton Generics [updated]

Tuesday, December 04, 2007 11:25 AM by mezhaka

the parameter type of the generic needs public default constructor, so the type you're using as a parameter is not singleton object itself. don't you think there maybe problems, when some other member of your team will use this parameter type instead of the using it singletoned with this generic?

Leave a Comment

(required) 
(required) 
(optional)
(required) 
Please add 7 and 1 and type the answer here: