views:

88

answers:

3

Hi all,

I've been looking at the article on creating static constructors in c# here:

http://csharpindepth.com/Articles/General/Singleton.aspx

Now, one option he doesn't mention is using a simple static constructor. Is there any issue with doing something like the below? If it works, it seems simpler than his complicated solutions IMHO.

public static class ServiceFactory
{
  static ServiceFactory()
  {
    container = new Foo();
  }
  static Foo container;

  public static Instance {
    get {
    return container;
    }
  }
}

The reason i ask is i'm doing a code review and want to leave it as-is if it's fine.

A: 

The question of the day is this: do you want lazy instantiation or not? If you do not need lazy instantiation and are perfectly fine with on-load instantiation, feel free to use the paradigm you have, or even use this somewhat less verbose version:

public static class ServiceFactory
{
    private static readonly container = new Foo();
    public static Instance { get { return container; } }
}

Both work fine and are perfectly valid -- as long as you don't need lazy. If you need lazy, use the Fifth version pointed out in the article.

Randolpho
I think his code is lazy since the static constructor is only called when the class is used for the first time.
CodeInChaos
But i thought what i've got *is* lazy, because i thought that static constructors are only called the first time a class is accessed?
Chris
@Chris: Yes, what you've got is lazy. It's just not a singleton.
Jon Skeet
+1  A: 

Your code is equivalent to his fourth example†, except you are using an explicit class constructor whereas he is initialising at point of declaration.

You should (in most cases) shy away from using the singleton pattern, as it makes it very hard to scale and unit-test an application.

† except there is a behavioural difference as to when the singleton is constructed when class constructors are used.

Paul Ruane
Singleton, depending on implementation, can be quite testable. If anything, a Singleton is *way* more testable than a bunch of static methods.
Randolpho
@Randolpho: I talk about the singleton pattern rather than singleton instances in general. I am not suggesting static methods (although they are harmless if pure functions).
Paul Ruane
@Paul Ruane: Ironically, I felt as you do that the Singleton pattern is fail for the longest time -- *until* I got heavy into unit testing, at which point I found I'd much rather use a well tested Singleton than, say, static methods.
Randolpho
@Randolpho: so how do you reset your stateful, singleton pattern instance between tests, so that one test does not interfere with the next?
Paul Ruane
According to that behavioural difference article you cited, using a static constructor as we have above is a better way to go - am i correct?
Chris
@Chris: It depends on what requirements you have in terms of timing.
Jon Skeet
@Chris: take it from the horse's mouth (no offense Jon :).
Paul Ruane
Timing requirements: i think as lazy as possible (create the object at the point when the Instance is called the first time).
Chris
+3  A: 

Your code isn't building a singleton. It's creating an instance of Foo, and presumably anyone else could too - which means it isn't a singleton.

You've created a single instance which is referred to by a static variable in ServiceFactory, but that's not the same thing.

Unless you have some class which you've restricted so that there can only ever be one instance of it, you don't have a singleton. You may have a factory pattern, a cache, whatever - but you don't have a singleton.

Now what you've got is equivalent to this:

static Foo container = new Foo();
static ServiceFactory()
{
}

... and I'm not sure why you think your version is simpler than the above. If you do want to actually create a singleton, you're going to need a private constructor for whatever class you're trying to turn into a singleton. At that point, you've basically got my fourth example, so again I'm not sure where you think you're making things simpler.

Of course, you may not need a static constructor at all - it depends on how precise you need the timing to be. (Read my article on beforefieldinit for more details, along with my blog post about the CLR v4 changes.)

Jon Skeet
Not sure if i can make the constructor private - the object in question is the Castle Windsor IOC container. But suggestions taken on board. Cheers!
Chris