Is it better to rely on IOC Framework to implemented singleton? I heard that either double checked locking or relying on static constructor are not good practice, is this true?
-
1I get a little tired of the whole "double-checked locking doesn't work" meme. *Properly implemented double-checked locking works just fine in .NET* ... that is not to say you are going in the right direction. I tend to avoid singletons whenever possible; they are frequently unnecessary. – Andrew Barber May 06 '11 at 14:48
-
@Andrew: The OP didn't say that it didn't work. They said they'd heard it was bad practice - which is something I concur with. It's fiddly to get right, and there are almost always simpler approaches which work just as well. (I'm fine with relying on a static constructor *if* it's doing relatively little work, mind you.) – Jon Skeet May 06 '11 at 14:51
-
@Jon Skeet - You are correct; not sure why I read "doesn't work" when that's not what he said. – Andrew Barber May 06 '11 at 14:54
-
@Jon Skeet the remarks of @Andrew Barber I would say are 90%+ attributable to you Skeet. Your blog specifically says that double checked locking would require some kind of "explicit memory barrier calls" but you never elaborate what that means nor what the implications of that statement are. – Chris Marisic May 06 '11 at 14:55
-
1@Chris: I've said that `volatile` makes it work, and that other memory barriers can make it work but that experts disagree about *exactly* what is required. I'm not going to try to give more information about what to do when experts disagree :) This is the reason I avoid DCL - it's easy to get wrong, and hard to reason about accurately. I like `Lazy
` in .NET 4 which I trust to do the right thing :) – Jon Skeet May 06 '11 at 14:58 -
@Jon Skeet you just reiterated my entire argument, you use the statement "other memory barriers can make it work", what does that even mean? – Chris Marisic May 06 '11 at 15:09
-
1@Chris: I was trying to explain *why* I wasn't going into more details. As for other memory barriers: things like calls to `Thread.MemoryBarrier`. – Jon Skeet May 06 '11 at 15:11
-
@Jon Skeet and now I understand what your talk of MemoryBarrier is in reference of as I've never seen that class ever before and reading the descriptions and comments left on it on the MSDN made my head hurt, especially from the comments pointing out inconsistencies. – Chris Marisic May 06 '11 at 15:53
-
@Chris: Right. When my head starts hurting while I try to verify that my code is correct, I look for an alternative approach :) – Jon Skeet May 06 '11 at 15:55
-
@Jon Skeet putting this all in further context, do these statements relate to why you want to use a static constructor to have the beforefieldinit or whatever directive fall out that without doing that puts you in a position that calls could be reordered such that you'd lose thread safety? – Chris Marisic May 06 '11 at 16:02
-
@Chris: The beforefieldinit bit is somewhat separate. The static constructor approach just removes the thread safety concerns of DCL. – Jon Skeet May 06 '11 at 16:03
-
@Jon Skeet right, I'm saying if you do not use that approach is that where it would require using MemoryBarrier? And that using the static ctor is a work around to this by having the code generated with the beforefieldinit that prevents the memory calls from being reordered so you can depend on thread safety (similar to the net result if you used MemoryBarrier correctly)? – Chris Marisic May 06 '11 at 16:13
-
@Chris: The safety of the static constructor is independent of whether you use beforefieldinit. That affects the *timing* of the initialization, not its safety. – Jon Skeet May 06 '11 at 16:34
4 Answers
In my opinion the lifetime of an object should be decided by the context creates it not enforced by the type of the object. In common sense not the ways to guarantee "singletonness" of an object are considered bad practice but the usage of the singleton pattern itself.
So, to answer your question: Yes, you should let the IoC container handle the lifetime of its objects.

- 14,478
- 1
- 35
- 53
Perhaps this answer may be helpful to you. It contains a basic pattern for a thread safe, lazy-loaded singleton.
It's pretty simply to implement the double checked locking pattern, and it's quite succinct and good practice. However, like @Andrew Barber said, improperly implementing it can be painful.
if(_instance == null)
{
lock(_myLockObject)
{
if(_instance == null)
_instance = new Something();
}
}
return _instance;

- 40,736
- 10
- 68
- 86
-
1I believe `_instance` should be declared `volatile` for this to be correct. – Jon Skeet May 06 '11 at 14:55
-
I'm curious about this. The MSDN documentation says you should use volatile when not using a lock - http://msdn.microsoft.com/en-us/library/x13ttww7(v=vs.71).aspx – Tejs May 06 '11 at 15:05
-
You're not within a lock when you perform the first check. Memory barriers etc get hideously complicated - there are concerns around the possibility of a reference being published before all the data within the object being published. This kind of thing is why I don't like it. – Jon Skeet May 06 '11 at 15:08
-
@Jon, I heard you have to declare not only _instance volatile, but all its properties volatile as well. – user705414 May 06 '11 at 15:13
-
Object lifetime as the general rule should always be handled by an IOC container.
Manual object lifetime handling is prone to developer error, SRP violations, and extensive DRY violations.

- 32,487
- 24
- 164
- 258