9

I found that in C# you can implement a Singleton class, as follows:

class Singleton
{

    private static Singleton _instance;
    public static Singleton Instance => _instance ??= new Singleton();

    protected Singleton() { }
}

Which works for instances of type Singleton, i.e:

var a = Singleton.Instance;
var b = Singleton.Instance;
Console.WriteLine(ReferenceEquals(a, b)); //Prints True.

But what if I want that derived classes of Singleton also follow the Singleton pattern, i.e:

class A:Singleton
{ ... }
A a = A.Instance;

In this case the static member Instance is accessed by Singleton class and creates a Singleton instance, which isn't the objective. Besides, there are two main problems with this solution:

  • The derived class can implement its own constructor and lose the Singleton Pattern.
  • If there is another instance of Singleton then the derived class is going to reference that less-derived instance

My question is: Is there another way to implement a Singleton class in C# ensuring that derived class are also singleton?

AustinWBryan
  • 3,249
  • 3
  • 24
  • 42
Robin Curbelo
  • 1,323
  • 1
  • 11
  • 21
  • 1
    interesting question, I suggest giving this a read: http://msmvps.com/blogs/jon_skeet/archive/2006/01/20/singleton-inheritance.aspx – Reza Shirazian May 31 '13 at 20:30

2 Answers2

26

Ignoring the usual "Don't use a Singleton, look at your design." arguments, you could conceivably implement one as thusly (assuming your derived classes have default constructors):

public abstract class Singleton<T> where T : class, new()
{
    private static T _instance;

    public static T GetInstance()
    {
        if(_instance == null)
            _instance = new T();
        return _instance;
    }
}

And derive like this:

public class SingletonA : Singleton<SingletonA> { /* .... */ }
public class SingletonB : Singleton<SingletonB> { /* .... */ }

But, I really don't advocate this singleton approach personally. They do have their (rare) uses, but they can turn out to be more of a pain in the bum - turning in to glorified global variable containers.

Also, be mindful of thread-safety.

Moo-Juice
  • 38,257
  • 10
  • 78
  • 128
  • 3
    I would also be cautious of using an Instance property rather than a GetInstance() method. There are some fun things that can happen if you mouse over the Instance property in the debugger while at a breakpoint hit due to a side effect of the Instance being constructed in the code. Granted, it's much better to a) avoid the Singleton pattern and b) avoid side-effects in their constructors. – Dan Bryant May 31 '13 at 20:30
  • @DanBryant, absolutely correct - have edited. – Moo-Juice May 31 '13 at 20:32
  • 1
    +1 for `"Don't use a Singleton, look at your design."`. – Darin Dimitrov May 31 '13 at 20:37
  • 3
    I'm a bit confused, your generic `Singleton` class requires `T` to have a public parameterless constructor, so none of the inherited classes are actually enforced to be singletons. And the `GetInstance` method is non-static (obviously) so in order to call it you need an instance, which should be obtained with `GetInstance`. – Dirk May 31 '13 at 20:46
  • @Dirk, the lack of a `static` on the `GetInstance` method was a typo, I have corrected it. – Moo-Juice May 31 '13 at 21:05
  • @Dirk, perhaps if you can expand your question (or ask a new one) as to *why* you want to do this, we can suggest better alternatives? – Moo-Juice May 31 '13 at 21:05
  • 5
    @Moo-Juice ok, with that typo fixed there is only one issue left: your `Singleton` class has a `new()` constraint which means that `T` must have a public constructor. And classes like `SingletonA : Singleton` can thus be simply created with new. Doesn't this defeat the purpose of a singleton? – Dirk May 31 '13 at 21:47
  • Using this technique, you must still declare a private constructor in the base class. – David Sep 09 '15 at 08:13
5

My question is: Is there another way to implement a Singleton class in C# ensuring that derived class are also singleton?

Well, you could have some sort of check within the constructor that:

  • The actual type of this is sealed
  • The actual type of this is a direct subclass of Singleton
  • No other instance of that type has been created (by keeping a HashSet<Type>)

However, it seems rather pointless. What is your base class actually meant to achieve?

The singleton pattern is easy to implement properly (which your example doesn't, by the way - it's not thread safe) so why have the base class? The base class itself wouldn't be a singleton (there would potentially be many instances - one per subclass) so what's the benefit?

It seems to me that "I'm a singleton for the actual type of the object" isn't an appropriate basis for inheritance in the first place, and frankly I'd try to avoid the singleton pattern as far as possible anyway.

If you really want a base class, it should be because there's some common functionality that all the subclasses naturally inherit. That's unlikely to be inherently to do with whether those subclasses are singletons.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • As to your last point... what about the following? I have a project, 'sProj', with a some static data stored in a singleton. There are two main projects that interface with it... 'maxProj' requires the whole data set (properties of the singleton), while the 'minProj' requires only a subset of the static data. Given that 'maxProj' uses the same functionality of 'minProj', doesn't it make sense to define a base singleton for the 'min' requirements, and inherit from it -- allowing me to share the resources – laventnc Apr 01 '20 at 15:13
  • @laventnc: I'm afraid it's very hard to understand relatively complex issues with just a code description. You might want to present your code on CodeReview and ask for a review there. – Jon Skeet Apr 01 '20 at 15:20