Readability Panel
Capitalise Main Text
Increase Word Spacing
Use another Font
More Coming Soon!!

Saturday, 10 August 2013

The Singleton Pattern in C#, its pitfalls and a Solution

The Singleton Pattern, for those who don't know, is a pattern that enforces single instantiation of a class where only one class is wanted. Like all patterns, one should be aware of the reasons for choosing to use a Singleton over a Static class. Sometimes it's said that the Singleton pattern is overused. I would contend that it is overused by those who have not given proper thought to whether they should be using a Singleton. On the other hand, if one has used a Singleton for one part of an application, it may make it easier to follow if other classes in that application behave in the same way. As per my first post on this blog, I code as part of a team. Code should be readable to not only me, but to anyone who comes to the code after me. This is a concept that seems to be forgotten by many. It's not your code. It's the team's code. If you've decided to do one part of the code one way, try to maintain that theme throughout.

On to the matter at hand...

Some would say that the Singleton Pattern is constructed thusly:

    public class MyClass
    {
        private static MyClass instance;

        public static MyClass Current
        {
            get
            {
                return instance ?? (instance = new MyClass());
            }
        }
    }

This is all well and good, but we'll have to rewrite this exact same code every single time we want a class to be a Singleton. There may also be variations: some might call the property "Instance" or "CurrentInstance" or "Singleton". Some might initialise the instance statically, obviating one of the points of using the Singleton pattern.
With this in mind, my first stab at solving the problem of repeated code (and inconsistent implementation) was to create a base class using Generics:

    public class MyClass : Singleton<MyClass>;
    {
    }

    public abstract class Singleton<T> where T : class, new()
    {
        private static T instance;
          
        public static T Current
        {
            get
            {
                return instance ?? (instance = new T());
            }
        }
    }

There are a couple of issues with this approach, however.

Firstly, while MyClass can implement an interface, it is immediately prevented from being a subclass. This might be acceptable if you want to enforce a rule that all Singletons have no Inheritance, but then you should also make all Singletons sealed and asking everyone to implicitly be aware of this could be a tall order.

Secondly, and perhaps more importantly, there's this messy scenario to consider:

    public class YourClass : Singleton<MyClass>
    {
    }

"You'd never do that!" - OK, you might never do that, but someone less experienced might. Someone who's trying to refactor your class without actually deleting it might copy your code and change the class name without changing the Generic. This little gem could cause some hilarity down the line. You can't put type checking into Singleton, because Current is static and consequently, GetType() is unavailable.

I thought about this problem a little, and it occurred to me that since we have Generics, and Activator.CreateInstance, there's no reason not to have a generic Singleton Factory. That is to say we have a static class whose job it is to maintain a keyed list of instances of types. The key is the Type, so it's impossible to have two items in the list being instances of the same Type.

    public static class SingletonFactory
    {
        private static readonly Dictionary<Type, object> instanceDictionary
                                = new Dictionary<Type,object>();

        public static T Get<T>() where T : class, new()
        {
            return (T) Get(typeof (T));
        }

        public static object Get(Type t)
        {
            lock (instanceDictionary)
            {
                if (!instanceDictionary.ContainsKey(t))
                    instanceDictionary.Add(t, Activator.CreateInstance(t));
                return instanceDictionary[t];
            }
        }
    }

This is a simple example. I've got a more advanced version that checks if the type is a class and whether it has a default constructor (public or otherwise) and will then invoke a private constructor if necessary. This enables me to protect classes intended to be used as Singletons from being accidentally instantiated by giving them private default constructors. Of course, others may still favour the Singleton base class - under which circumstances, you might imagine it possible to create an instance of the Singleton with the Factory and another instance from the Base Class. We can deal with that too:

    public abstract class Singleton<T> where T : class, new()
    {
        public static T Current
        {
            get { return SingletonFactory.Get<T>(); }
        }
    }

Here, the Singleton Base Class uses the SingletonFactory as its source of the instance of T instead of holding its own private reference.

After creating the Singleton Factory, I thought to myself "This can't be an uncommon problem." All the same, I hadn't really heard anyone complaining about problems with Singletons. I had a quick Google, and it turns out the Singleton Factory has been around for a while in the land of Java, but it's seen less frequency in C#.

No comments :

Post a Comment