Can I use a singleton with a non-default constructor in C #?

This is a slight deviation in this question: Can I use a singleton with a non-default constructor in C #?

I have a class that takes parameters for its constructor. I would like to make this singleton so that the parameters are taken when the singlet was initialized and, therefore, it did not need to be passed every time the instance is retrieved.

My solution (which is not elegant) for this is to have a static CreateInstance() method that takes parameters and constructs a singleton instance. Then I would have another static GetInstance() method, which would be without parameters to get a singleton instance. In the code, I would need to provide the logical calls to CreateInstance before any calls to GetInstance. However, I cannot provide this at compile time. However, I can check at runtime by throwing an exception in GetInstance if it is called before CreateInstance .

In any case, can I achieve this behavior while compiling time? Or at least is there a better way to do the same?

+6
parameter-passing c # singleton
source share
6 answers

There is no way to do this at compile time, because it will be like a compiler request: "Can you prove that the X code is never executed before the Y code runs when there are multiple threads?" This is impossible to do.

Regarding the runtime behavior of your project, I think it is as good as it can be.

You can do this a little better by exposing the Func<SingletonType> property in your singleton class. When someone requests a singleton instance and the instance has not yet been created, your class will call this method "factory" to build a singleton. If the factory method is null , you either throw an exception, or (if applicable) a construct using some default parameters.

What this does is essentially delaying the construction of the singleton until it is really needed for the first time, so this is some improvement. But the basic principle is the same.

Update:

As LukeH points LukeH , this is pretty much what Lazy<T> does (.NET 4 only). If possible, use this option instead of writing your own.

+5
source share

In a classic singlet, the real magic happens in static readonly , which creates an instance immediately after using it:

 public class MySingleton { private static readonly _instance = new MySingleton(); private MySingleton() {} public static MySingleton Instance { get { return _instance; } } } 

If you have parameters to go to the constructor, you need to implement a lock (note the double if rewind lock ):

 public class MySingletonWithConstructor { private static _instance; private static object _lock = new Object(); private MySingletonWithConstructor(string myArg) { // ... do whatever necessary } public static MySingletonWithConstructor Instance { get { if(_instance==null) { lock(_lock) { if(_instance==null) // double if to prevent race condition { _instance = new MySingletonWithConstructor("Something"); } } } return _instance; } } } 
+1
source share

You can simply GetInstance() call the CreateInstance() method if the singleton object no longer exists.

0
source share

I would make it look like this. You may need to add locks or other things to ensure:

  public class ClassA { private static ClassA instance; private int param; private ClassA(int param) { this.param = param; } public static ClassA getInstance() { if (instance == null) { throw new CustomException("Not yet initialised"); } else { return instance; } } public static void createInstance(int param) { if (instance == null) { instance = new ClassA(param); } } } 
0
source share

In your GetInstance() method, why don't you just call CreateInstance, if your value is null, then you have lazy initialization.

0
source share

Use CreateInstance () to be the Lazy<T> loader, and GetInstance returns Lazy.Value (you can create a static readonly field that has value = thelazy.Value set to provide a single entry in CreateInstance ())

0
source share

All Articles