5

I am trying to create a generic singleton base class like

public class SingletonBase<T> where T : class, new()
{
    private static object lockingObject = new object();
    private static T singleTonObject;
    protected SingletonBase()
    {

    }

    public static T Instance
    {
        get
        {
            return InstanceCreation();
        }
    }
    public static T InstanceCreation()
    {
        if(singleTonObject == null)
        {
             lock (lockingObject)
             {
                  if(singleTonObject == null)
                  {
                       singleTonObject = new T();
                  }
             }
        }
        return singleTonObject;
    }
}

But I have to make constructor as public in derived one.

public class Test : SingletonBase<Test>
{
    public void A()
    {

    }
    private Test()
        : base()
    { }
}

Compilation Error:

'Test' must be a non-abstract type with a public parameterless constructor in order to use it as parameter 'T' in the generic type or method 'Test'

How can I achieve this?

Javier
  • 12,100
  • 5
  • 46
  • 57
D J
  • 6,908
  • 13
  • 43
  • 75
  • 2
    I think this answer is probably quite relevant: http://stackoverflow.com/a/380771/120243 – Alastair Pitts Mar 25 '13 at 04:10
  • I think your sample code is wrong. It builds fine. Just a guess, but I think you meant that your error was related to `PermissionController` in which case `PermissionController` must have a public paramerterless constructor to satisfy the `new()` constraint on `T`. – Jason Watkins Mar 25 '13 at 04:12
  • @AlastairPitts :- That answer still is not singleton. – D J Mar 25 '13 at 04:17
  • @JasonWatkins :- Thanks for pointing error. I updated the sample code. – D J Mar 25 '13 at 04:19
  • 1
    @DJ Yes it is. It doesn't use locking as it's using statics, but it's definitely a singleton. It probably should have a static constructor, but it's completely valid. See: http://csharpindepth.com/Articles/General/Singleton.aspx – Alastair Pitts Mar 25 '13 at 04:22
  • @Alastair It _does_ have an implicit static constructor. For nearly all practical purposes the field assignment in the class can be considered part of the static constructor. adding an empty explicit static constructor changes absolutely nothing practically speaking. – Jason Watkins Mar 25 '13 at 04:24
  • Actually it's not thread safe: `singleTonObject = new T();` use temporary `variable var temp = new T(); singleTonObject = temp;` – Andrew Mar 25 '13 at 04:31

2 Answers2

7

The problem is your generic constraint where T : class, new(). The new() constraint requires a public, parameterless constructor on T. There is no way around this; you need to provide such a constructor in Permission Controller.

Jason Watkins
  • 3,766
  • 1
  • 25
  • 39
  • +1. this is actually the correct answer to OP's original issue. My answer had more to do with the overall design pattern. – p.s.w.g Mar 25 '13 at 04:38
  • hmm.. OK.. I think I need to choose some other direction. Thanks – D J Mar 25 '13 at 05:47
3

I would avoid this kind of recursive generic pattern. Read this this blog post for a detailed explanation of the pattern and reasons not to use it.

As far as I can tell, you don't need to have any sub-classes of SingletonBase<T>. I can't see anything that a subclass of SingletonBase<T> would be able to add to your code. I would simply rewrite it as

public static class Singleton<T> where T : class, new()
{
    ...
}

You can then use it as

var test = Singleton<Test>.Instance;

If you want to be able to use Test as a singleton, create it as

public class Test 
{
    public static T Instance
    {
        get { return Singleton.Instance<Test>; }
    }
}
p.s.w.g
  • 146,324
  • 30
  • 291
  • 331
  • Presumably the posted code is a reduced test case. – Jason Watkins Mar 25 '13 at 04:12
  • Could you please explain how you think the linked blog post applies to this question? I don't see it. – Jason Watkins Mar 25 '13 at 04:28
  • @JasonWatkins it applies to the pattern OP is using -- `class Test : Singleton`. – p.s.w.g Mar 25 '13 at 04:31
  • But that's Eric's post is talking about recursive *constraints*, not simple inheritance from a generic class. – Jason Watkins Mar 25 '13 at 04:35
  • 1
    @JasonWatkins It's true OP's code did not contain recursive constraints, but it was probably intended to be used as though it did. I think it's implicit in the singleton pattern. After all `Foo : Singleton` would mean `Foo.Instance` is a `Bar` -- which may be valid, but kind of breaks the whole singleton design pattern. – p.s.w.g Mar 25 '13 at 04:48