33

This is how I write my singleton classes.

public class MyClass
{
    /// <summary>
    /// Singleton
    /// </summary>
    private static MyClass instance;

    /// <summary>
    /// Singleton access.
    /// </summary>
    public static MyClass Instance
    {
        get
        {
            if (_instance == null)
            {
                _instance = new MyClass();
            }
            return _instance;
        }
    }

    private MyClass() { .... }
}

How To Create A Singleton Pattern That Is Reusable?

Singleton patterns present the following challenges.

  • The constructor is private or protected.
  • A base class can't instantiate an inherited class. So you can reuse a common abstract MyAbstractSingletonClass.
  • It has to have a local read-only property to get the instance.

The Problem

I'm using this pattern on a number of classes and always have to write the same code. How can I write something that is reused whenever I need a singleton?

Reactgular
  • 52,335
  • 19
  • 158
  • 208
  • I'm trying to understand what you're trying to accomplish here. Do you want the base class to have knowledge of the derived class, and return that, or are you wanting the base class to just "know" somehow to return the only class derived from it? Can you add a static function to the base class called `Initialize(string type)` or something to tell the base class what to initialize the single instance with? A little more clarification on what you're trying to do and what your constraints are would help. – Gjeltema May 25 '13 at 01:49
  • @Gjeltema I edit my question. Hope that helps. – Reactgular May 25 '13 at 02:04
  • 2
    Yep, it did, but BTownTKD beat me to typing up the answer. :) – Gjeltema May 25 '13 at 02:09

8 Answers8

61

You can achieve this using a combination of a self-referencing generic type constraint, and a "new()" type constraint.

The "new" constraint ensures that any child class will always have a parameterless constructor, so _instance = new T(); will always work.

The self-referencing type constraint ensures that the "Instance" static property always returns the correct Type; not the "base" type. Your singleton base class would look something like this:

public abstract class SingletonBase<T> 
    where T : SingletonBase<T>, new()
{
    private static T _instance = new T();
    public static T Instance
    {
        get
        {                
            return _instance;
        }   
    }
}

Your child classes will look like this:

public class MyChildSingleton : SingletonBase<MyChildSingleton>
{
    //Done!
}

Of course, if you want your singleton to be general-purpose, you should also change your "create singleton instance" code slightly, to use the "double-check lock" pattern, or the Lazy class, to make it thread-safe.

The big caveat: if you use this method, the "new()" constraint pretty much ensures that your class will always have a public, parameterless constructor. That means your end-users could always just call new MyChildSingleton() if they really wanted, bypassing your singleton instance entirely. Your singleton would be "by convention," instead of strictly enforced. To get around this would take a bit more engineering. In the above scenario, the convention seems to be that you should name your static instance "Default" instead of "Instance." This subtly conveys the fact that your class offers a 'suggested' singleton instance, but using it is technically optional.

I've made some attempts to strictly enforce the singleton pattern, and the end result was to use reflection to manually invoke a private constructor. You can see my full code attempt here.

BTownTKD
  • 7,911
  • 2
  • 31
  • 47
  • 6
    @MathewFoscarini - please check out Jon Skeet's article on Singletons before using this code as is: http://csharpindepth.com/Articles/General/Singleton.aspx as it may require some multithreading touches and could benefit from `Lazy` class. – Alexei Levenkov May 25 '13 at 02:14
  • 1
    It's actually pretty simple to restrict a constructor call in runtime (not sure possible in compilation). All you do is add a protected constructor in SingletonBase, that throws an exception if _instance is not null. The exception will be thrown even if the constructor is the first thing to be called from outside. – Eugene Marin Apr 21 '16 at 15:39
  • 3
    These types are not singletons. You have to have a public constructor on those types to meet that generic constraint, so anyone can create new instances of them, making them not singletons. – Servy Jul 14 '16 at 13:07
22

The true solution is starting with BTownTKD's approach but augmenting it with the Activator.CreateInstance method which allows your child classes to keep the private constructors.

Parent Class

public abstract class SingletonBase<T> where T : SingletonBase<T>
{
    private static readonly Lazy<T> Lazy =
        new(() => (Activator.CreateInstance(typeof(T), true) as T)!);

    public static T Instance => Lazy.Value;
}

Child Class

public sealed class MySingleton : SingletonBase<MySingleton>
{
    private MySingleton() { }
}

Full Implementation Example Here

Buvy
  • 1,174
  • 12
  • 16
  • 5
    I am not sure why this is not the accepted answer or why this hasn't received any upvotes. The only caveat I can think of for this solution is that the presence of a private parameterless-constructor can only be enforced at run time instead of at compile time. Other than that, however, this is by far the most powerful solution listed here. – Teun Kooijman Dec 21 '17 at 20:48
  • 1
    This answer is fine, with the exception that you should probably use Lazy instead of ThreadLocal. If something is only "Singleton per thread," then it isn't really "Singleton." – bopapa_1979 May 14 '20 at 20:47
5

Adding to BTownTKD's answer, it's actually pretty simple to restrict a constructor call in runtime (not sure possible in compilation). All you do is add a protected constructor in SingletonBase, that throws an exception if _instance is not null. The exception will be thrown even if the constructor is the first thing to be called from outside.

I managed to apply this technic in a singleton base, and also make it lazy and thread safe as described here: http://csharpindepth.com/Articles/General/Singleton.aspx

The result (with usage explanation):

/// <summary>
/// Generic singleton class, providing the Instance property, and preventing manual construction.
/// Designed as a base for inheritance trees of lazy, thread-safe, singleton classes.
/// Usage:
/// 1. Sub-class must use itself, or its sub-class, as the type parameter S.
/// 2. Sub-class must have a public default constructor (or no constructors).
/// 3. Sub-class might be abstract, which requires it to be generic and demand the generic type
///    have a default constructor. Its sub-classes must answer all these requirements as well.
/// 4. The instance is accessed by the Instance getter. Using a constructor causes an exception.
/// 5. Accessing the Instance property in an inner initialization in a sub-class constructor
///    might cause an exception is some environments.
/// </summary>
/// <typeparam name="S">Lowest sub-class type.</typeparam>
public abstract class Singleton<S> where S : Singleton<S>, new()
{
    private static bool IsInstanceCreated = false;
    private static readonly Lazy<S> LazyInstance = new Lazy<S>(() =>
        {
            S instance = new S();
            IsInstanceCreated = true;
            return instance;
        });

    protected Singleton()
    {
        if (IsInstanceCreated)
        {
            throw new InvalidOperationException("Constructing a " + typeof(S).Name +
                " manually is not allowed, use the Instance property.");
        }
    }

    public static S Instance
    {
        get
        {
            return LazyInstance.Value;
        }
    }
}

I must say I haven't done intensive multi-threading testing, but as some already said, you can always use the old double-check trick.

Eugene Marin
  • 1,706
  • 3
  • 23
  • 35
  • Thank you for this! I found I had to slightly tweak to prevent instantiation manually. IsInstanceCreated = true had to be set before new S(), and the InvalidOperationException had to be thrown if !IsInstanceCreated. Otherwise it only worked after a singleton was created, but not if the class was instantiated manually first. – Jamieson Rhyne May 16 '17 at 13:16
  • @JamiesonRhyne We do need both: `WillInstanceCreate = true` set before `new S()` and `IsInstanceCreated = true` afterwards. The exception has to be thrown `if (!WillInstanceCreate || IsCreated)`. – Olli Jul 11 '19 at 07:02
4

Implementing the singleton pattern in a base class is a questionable practice.

However, you can implement other creational design patterns that may be suitable for what you're trying to accomplish. For example, take a look at Abstract Factory.

Ilya Kogan
  • 21,995
  • 15
  • 85
  • 141
2

You are correct - as it currently stands you cannot achieve this. But you can approach it using generics, note that with this approach you will get one singleton instance for each unique derived type:

namespace ConsoleApplication2
{
    class Program
    {
        static void Main(string[] args)
        {
            var x = new MyDerivedClass();
            Console.WriteLine(x.ToString());
            Console.WriteLine(x.Instance.ToString());

            Console.ReadKey();
        }
    }


    public abstract class MyBaseClass<T> where T : class, new()
    {
        protected T GetInstance()
        {
            if (_instance == null)
            {
                lock (_lockObj)
                {
                    if (_instance == null)
                        _instance = new T();
                }
            }
            return _instance;
        }

        public T Instance
        {
            get { return GetInstance(); }
        }

        private volatile static T _instance;
        private object _lockObj = new object();
    }

    public class MyDerivedClass : MyBaseClass<MyDerivedClass>
    {
        public MyDerivedClass() { }
    }

}
slugster
  • 49,403
  • 14
  • 95
  • 145
  • 3
    Your derived classes all *must* have a public constructor, meaning anyone who wants to can create new instances, meaning they're not singletons, since there can be more than one instance of them. – Servy Jul 14 '16 at 13:08
2

I believe with @Buvy's solution, you will get an instance per thread which may be what he intended. You will have to modify it a bit to get a single instance across threads.

public abstract class BaseSingleton<T> 
    where T : BaseSingleton<T>
{
    private static readonly Lazy<T> lazy =
                    new Lazy<T>(() => Activator.CreateInstance(typeof(T), true) as T);

    public static T Instance { get { return lazy.Value; } }

}
jalley
  • 105
  • 1
  • 5
  • Assuming the originator wanted a multi-threaded, thread-safe implementation with PRIVATE constructors on derived types, then this is the best answer here. – bopapa_1979 May 14 '20 at 22:02
0

I recently suggested this answer to a related question:

https://stackoverflow.com/a/20599467

With this method, the base class manages creation of all instances of derived classes, as all derived class constructors require an object that only the base class can provide, and there is no need for the parameterless constructor restriction.

Community
  • 1
  • 1
dan
  • 49
  • 2
  • Really, for SingleTone class, it should have a private parameterless constructor. Have a look http://csharpindepth.com/Articles/General/Singleton.aspx – M.Hassan Aug 19 '18 at 00:18
0

My suggested example:

base class

public abstract class SingletonBase<T> where T : class
{
  private static readonly Lazy<T> sInstance = new Lazy<T>(() => CreateInstanceOfT());

  public static T Instance { get { return sInstance.Value; } }

  private static T CreateInstanceOfT()
  {
    return Activator.CreateInstance(typeof(T), true) as T;
  }
}

Usage

public class yourClass : SingletonBase<yourClass>
{
   public yourMethod()
   {
   }
}

use your singleton class like this:

yourClass.Instance.yourMethod();

for more info see my answer source in this link

Hasan Fathi
  • 5,610
  • 4
  • 42
  • 60