The quest for the Generic Singleton in C#

Abstract

While it is a bit tricky to implement the Singleton pattern in C#, the steps necessary are well known. There has however been debate about a generic solution for this. This paper provides 3  possible solutions for the generic singleton, and makes a brief comparison.

The Generic Singleton Pattern in C#

A Singleton is a class of which only one instance can exist in the application domain. As simple as this sounds, problems concerning thread-safety arise for the implementation in C#. Fortunately, Jon Skeet provided a neat article [1] describing how to pull this off correctly. There are quite a few catches to watch out for, and it would be nice if we wouldn't have to bother about them while creating a Singleton. This is where the idea of the Generic Singleton comes in. Wouldn't it be nice if we could create a class, not worrying about thread safety or private constructors at all. Then, once we decide it's a good idea to create a singleton, we just pass it as a generic parameter to a GenericSingleton class and voila: we have a construction that ensures there can be only one instance of our class! Many solutions have been proposed in books and on blogs and posts. They all basically boil down to this example, taken from Bishop's book on Design Patterns [2]:

public class Singleton<T> where T : class, new()

{

    Singleton() { }

 

    class SingletonCreator

    {

        static SingletonCreator() { }

        // Private object instantiated with private constructor

        internal static readonly T instance = new T();

    }

 

    public static T UniqueInstance

    {

        get { return SingletonCreator.instance; }

    }

}

While this code provides thread-safety and enforces that only one instance of class T can be created through the Singleton class, it has a major drawback. The generic constraint 'new()' on the type parameter means that the class T will have to provide a public parameterless constructor. This means that any client code will be able to create as many instances of class T as it likes. Thus, this breaks the Singleton pattern. It only works if client code is willing to only access class T via the Singleton class. But there is nothing that forces client code to only use it the way it was intended. While it is in general not necessary for an implementation of a design pattern to robustly exclude all misuse, it should do so as much as possible. The least thing an implementation of a design pattern should do, is encourage the intended use while discouraging misuse.

The solution with the delegate-constructor handshake

So, for the above Generic Singleton implementation to really work, we need to make sure that the public parameterless constructor cannot be called from any other class than the above Generic Singleton.

Easiest way to do this:

 

public class ReadyForGenericSingleton

{

    public ReadyForGenericSingleton(Singleton<ReadyForGenericSingleton> caller)

    {

        if (caller == null)

        {

            throw new Exception();

        }

    }

}

Alternatively, we could use the System.Reflection and/or System.Diagnostics namespaces to collect information about the caller. This is more transparant.  But it does have 3 complications. First of all, we inject the caller object into the constructor, and thus no longer fulfill the 'new()' generic constraint: we will have to change this. Second, we will have to have an calling instance, which is not the case in Bishop's solution. We need to change the code to create an instance of the Singleton class. And third, we have an ugly exception. We need to stop the constructor from creating a new object. In an instance constructor, we do not have many options to accomplish this. It is better here to use a 'static factory method' in Joshua Bloch's sense of the term [3]. Consider the following solution:

 

public sealed class ReadyForGenericSingleton

{

 

    public static ReadyForGenericSingleton CreateInstance(GenericSingleton<ReadyForGenericSingleton>

                                              caller)

    {

        if (caller != null)

        {

            return new ReadyForGenericSingleton();

        }

        else

        {

            return null;

        }

    }

 

    private ReadyForGenericSingleton() { }

}

 

public class GenericSingleton<T> where T : class

{

    private static T _instance = null;

    static readonly object padlock = new object();

    public delegate T CreateInstance(GenericSingleton<T> caller);

    private static CreateInstance _createInstance;

 

    public GenericSingleton(CreateInstance createInstance)

    {

        if (createInstance == null) throw new ArgumentNullException();

        _createInstance = createInstance;

    }

 

    public T UniqueInstance

    {

        get

        {

            lock (padlock)

            {

                if (_instance == null)

                {

                    _instance = _createInstance(this);

                }

                return _instance;

            }

        }

    }

 

}

Use (fragment of NUnit test):

ReadyForGenericSingleton rs1 = new GenericSingleton<ReadyForGenericSingleton>(ReadyForGenericSingleton.CreateInstance).UniqueInstance;

ReadyForGenericSingleton rs2 = new GenericSingleton<ReadyForGenericSingleton>(ReadyForGenericSingleton.CreateInstance).UniqueInstance;

 

Assert.IsTrue(rs1.equals(rs2));

Here, we created a GenericSingleton class that can have many instances. It is based on the simplest thread-safe example Jon Skeet provides: thread-safety through a lock-object. There are two things to note however: it does enforce a maximum of 1 instance of the class T that is taken as a generic type parameter, and it must be provided with a pointer to a method that creates an instance of type T based on an instance of the GenericSingleton class. If the instance is null, no new object is created and null is returned: no ugly exception necessary; this is the advantage of using a static factory method over a constructor. The static factory method can only create a new instance of the class if it is provided with the instance of the GenericSingleton class; the GenericSingleton class can only be constructed if it is given the pointer to the static factory method through the CreateInstance delegate. This is what we call the 'delegate-constructor handshake'. 

So, in this solution, what do we need to do if we want to turn a class into a singleton making use of the GenericSingleton class we presented above?

  1. Create a static factory method that takes the GenericSingleton as a parameter and checks it isn't null.
  2. Make sure there are no other properties, constructors or methods that allow client code to create instances of this class.
  3. Make the class sealed to deny client code to inherit from this class and hide the static factory method through the 'new' keyword, thus disturbing the 'delegate-constructor handshake'.

The solution with the Generic Singleton as an abstract class

The key problem of a generic singleton solution, is that we need a way to construct an instance of a class from the code of the generic singleton class, but we don't want to allow other code to be able to create new instances of the class. We solved this problem in the paragraph above with the 'delegate-constructor handshake'. But there is another solution: we can use the 'protected' keyword that allows access from inheriting classes, but no other classes. Thus, if we create a generic singleton class that is abstract, make our class inherit from it and provide it with a way to create a new instance using 'protected' access, we are nearly there. Last step would be to once again make our class 'sealed' to make sure no class can inherit it and abuse the 'protected' access to create multiple instances. This yields a solution like this:

public abstract class AbstractGenericSingleton<T> where T : AbstractGenericSingleton<T>

{

    private static T _instance;

 

    protected static bool Initialised

    {

        get

        {

            return (_instance != null);

        }

    }

 

    protected static T UniqueInstance

    {

        get

        {

            if (Initialised)

            {

                return SingletonCreator.instance;

            }

            else

            {

                return null;

            }

        }

    }

 

    protected AbstractGenericSingleton() { }

 

    protected static void Init(T newInstance)

    {

        if (newInstance == null) throw new ArgumentNullException();

 

        _instance = newInstance;

    }

 

    class SingletonCreator

    {

        static SingletonCreator() { }

 

        internal static readonly T instance = _instance;

    }

 

}

 

public sealed class ReadyForGenericSingleton : AbstractGenericSingleton<ReadyForGenericSingleton>

{

    public static ReadyForGenericSingleton Instance

    {

        get

        {

            if (!Initialised)

            {

                Init(new ReadyForGenericSingleton());

            }

 

            return UniqueInstance;

        }

    }

 

    private ReadyForGenericSingleton() { }

}

Use (fragment of NUnit test):

ReadyForGenericSingleton rs1 = ReadyForGenericSingleton.UniqueInstance;

ReadyForGenericSingleton rs2 = ReadyForGenericSingleton.UniqueInstance;

 

Assert.IsTrue(rs1.equals(rs2));

Here, we stayed as close to the Singleton class that Bishop provides as possible. Hence, we make a lot of use of the 'static' keyword. As C# does not allow static members to be marked 'abstract', 'virtual' or 'override', we cannot have a Template Method-like construction for a static 'NewInstance' property. We can however create a protected method in the abstract base class that allows the deriving class to set the instance. A protected getter allows the deriving class to pass it to the 'SingletonCreator' inner class to set it as the unique instance, and then return this unique instance. This solution however, requires a correct implementation in the deriving class. Another thing to note here, is that the GenericSingleton class has become abstract, and that the constraint on the generic type parameter T has changed to be an implementation of this abstract class itself.

If we would like to turn a class into a singleton making use of this solution, we would have to take the following steps:

  1. Have the class derive from the AbstractGenericSingleton class.
  2. Create a new public static getter property to provide client code with an instance
  3. Check the 'Initialised' property of the abstract base class, if false: pass in a new instance of the class to the 'Init' method, and return the result of the base class' 'UniqueInstance' property.
  4. Make sure there are no other properties, constructors or methods that allow client code to create instances of this class.
  5. Make the class sealed to deny client code to inherit from this class and hide the property that provides the instance.

The solution that uses Reflection to access a private constructor

There is yet another way to have the generic singleton create an instance of our class, while denying client code to do so. It feels a bit like cheating: we simply bypass the problem by stepping out of the generics-inheritance-encapsulation possibilities, and solve the problem by convention rather than by design. The System.Reflection namespace offers many tools to access, query and invoke members and constructors of classes. Anything public can be invoked regardless of Code Access Security. If the GenericSingleton code is allowed ReflectionPermission, also internal, protected and private members can be invoked. All we ask of the class that is to play along with this generic singleton solution, is that it has a private parameterless constructor. This yields a solution like this:

public class Singleton<T> where T : class

{

    Singleton() { }

 

    class SingletonCreator

    {

        static SingletonCreator() { }

 

        private static T CreateInstance()

        {

            ConstructorInfo constructorInfo = typeof(T).GetConstructor(BindingFlags.Instance |

                BindingFlags.NonPublic, Type.DefaultBinder, Type.EmptyTypes, null);

 

            if (constructorInfo != null)

            {

                return constructorInfo.Invoke(null) as T;

            }

            else

            {

                // alternatively, throw an exception indicating the type parameter

                // should have a private parameterless constructor

                return null;

            }

        }

 

        internal static readonly T instance = CreateInstance();

    }

 

    public static T UniqueInstance

    {

        get { return SingletonCreator.instance; }

    }

}

 

public class ReadyForGenericSingleton

{

    private ReadyForGenericSingleton() { }

}

Use (fragment of NUnit test):

ReadyForGenericSingleton rs1 = ReadyForGenericSingleton.UniqueInstance;

ReadyForGenericSingleton rs2 = ReadyForGenericSingleton.UniqueInstance;

 

Assert.IsTrue(rs1.equals(rs2));

The SingletonCreator inner class here has a private static method that uses reflection to determine the constructor to invoke. One of the benefits using reflection brings, is that it allows us to check the given generic type parameter for public constructors, non-private methods and properties that return instances of the type itself. One of the downsides of this solution by convention, is that we can only inform the client code that there is something wrong at runtime. Whereas a solution by design can provide much of this inormation at compile time. But the most severe objection to this solution is that is depends on Code Access Security configuration. It should allow (the assembly with) the GenericSingleton code to invoke private members, while at the same time denying client code the right to do the same. This is annoying and unsafe, but the real problem is that it must be configured in the environment that hosts the client application, that is typically not under our control.

If we would like to turn a class into a singleton making use of this solution, we would have to take the following steps:

  1. Make sure the class has a private parameterless constructor.
  2. Make sure there are no other properties, constructors or methods that allow client code to create instances of this class.

A brief comparison of the 3 solutions

The solution using reflection is certainly the easiest to use for client code. The other two solutions are somewhat cumbersome. With both, there are still some quirks to watch out for. Both rely on the correct implementation of (easy) logic by the class that is to be a singleton. So the question arises if they actually provide any advantage over using the non-generic recipe for creating a singleton.

The solution using reflection is certainly the nastiest to configure in the client application environment. It is also true that any singleton implementation can be broken by client code that has the Code Access Security ReflectionPermission. But it is quite a different thing for a solution to be broken by this right than requiring this right in order to work at all.

Of course, reflection in itself is not a bad thing. In our situation, with any of the 3 above solutions, it seems a good idea to use reflection to make sure no public constructors and /or members returning the type itself exist.

The solution with the generic singleton as abstract class feels a bit more intuitive. It also is a bit less demanding for the class that is to be a singleton: it does not actively have to deny non-GenericSingleton the right to obtain a new instance, as is the case with the solution with the 'delegate-constructor handshake'. The solution with the 'delegate-constructor handshake' also is a bit counter-intuitive in that it uses a lot of instances of the GenericSingleton class. While this is in principle not a problem, since the crucial point is to allow only 1 instance of class T, it feels odd and unnecessary, and results in awkward client code.

Concluding, none of the above solutions provide us with a way to create a singleton without bothering about enforcing it to be a singleton. If you need to use a lot of singletons (e.g. for caching purposes), it might be nice to use one of the solutions to encapsulate the 'singleton-ness' into common code. It is up to you to decide whether this advantage outweighs the difficulties of any of the solutions presented in this article. We did not reach the utopic situation of creating a singleton without bothering about constructors and static initialisation in this article. Hopefully it will arise with the introduction of a 'singleton' language construct in a future version of C#......

References

 

Up Next
    Ebook Download
    View all
    Learn
    View all