§ October 4, 2006

A Generic Singleton Pattern in C#

I don't know why its never occured to me to implement the singleton pattern as a generic type before. I've always just created the singleton pattern as part of my class (not that we're talking about a lot of coding here), but it occured to me that a singleton could be a lot easier to implement and spot if I used a generic type.

Here is my generic Singleton class:
public class Singleton<T> where T : class {
    static object SyncRoot = new object( );
    static T instance;
    public static T Instance {
        get {
            if ( instance == null ) {
                lock ( SyncRoot ) {
                    if ( instance == null ) {
                        ConstructorInfo ci = typeof( T ).GetConstructor( BindingFlags.NonPublic | BindingFlags.Instance, null, Type.EmptyTypes, null );
                        if ( ci == null ) { throw new InvalidOperationException( "class must contain a private constructor" ); }
                        instance = (T)ci.Invoke( null );
                    }
                }
            }
            return instance;
        }
    }
}


Now, instead of implementing this same thing in every single class you want to act as a singleton, you simply use the generic definition: Foo.Instance.Whatever turns into Singleton<Foo>.Instance.Whatever.

Update: I've updated this implementation from using a mutex to using a simple lock (double checked) object. A mutex is pointless for a singleton (which I may go into in another article at some later time) as you can never have 2 separate execution contexts accessing one singleton anyway (which is where you would need a mutex over a simple lock object), and I changed the where T : new() to where T : class and changed the instantiation to use reflection to call the private default constructor instead, which I think is the correct implementation.
Posted 19 years, 6 months ago on October 4, 2006

 Comments can be posted in the forums.

© 2003 - 2024 NullFX
Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License