A friend of mine recently sent me some code to review:
Hi Peter,
Do you have any suggestions on how to clean up this code?
In particular the creation of a particular singleton type doesn't look very pretty in this model:
private DoubleCheckedLock<SingletonClass> myInstance = new DoubleCheckedLock<SingletonClass>();
public SingletonClass Current {
get {
return this.myInstance.GetSingleton(
delegate() {
return this.CreateSingleton(OrderContext, "third");
}
);
I’m sharing my comments on the code, as it demonstrates some important design principles. Here’s the original code:
public class DoubleCheckedLock<T> where T : class
{
private volatile T myInstance;
private static readonly object lockObject = new object();
public T GetSingleton(CreateObject c) {
if (this.myInstance == null) {
lock (lockObject) {
this.myInstance = c();
Debug.Assert(this.myInstance != null);
return this.myInstance;
public delegate T CreateObject();
public abstract class DoubleCheckedLock2<T> where T : class
protected abstract T CreateObject();
private DoubleCheckedLock<T> myInstance = new DoubleCheckedLock<T>();
public T Instance {
return this.myInstance.GetSingleton(this.CreateObject);
And here are my comments:
Now the client code looks like this:
sealed class Client {
private readonly Singleton<ExpensiveResource> expensiveValue;
Client() {
this.expensiveValue =
new Singleton<ExpensiveResource>(
delegate()
return new ExpensiveResource();
public ExpensiveResource ExpensiveValue {
get { return this.expensiveValue.Value; }
Which is pretty damn sexy, if I don't say so myself.
Here's the implementation:
public delegate T Creator<T>();
public class Singleton<T> where T : class {
private readonly Creator<T> creator;
public Singleton(Creator<T> creator) {
Debug.Assert(creator != null);
this.creator = creator;
public T Value {
this.myInstance = this.creator();
this.creator = null; // allow creator object to be GC-ed as soon as possible
Happy coding,
Peter