Click here to Skip to main content
15,884,472 members
Articles / Programming Languages / C#
Tip/Trick

Thinking in Singleton instead of A Useful Generic Singleton Template

Rate me:
Please Sign up or sign in to vote.
4.75/5 (6 votes)
13 Dec 2013CPOL4 min read 31.3K   5   16
This is a singleton template class which can be used by classes with a private constructor.

Introduction

I wrote this article named "A useful generic singleton template". I got several replies which indicated my odd article's defects. I decided to make a resume for these useful replies and compose a new article for singleton.

My original article can be found in the History chapter of this article. I wish to thank CodeProject members who left very useful replies : Brien Givens, mike75 and those who will give different ideas in the future.

Background

I use often Singleton in my project. I use singleton class for creating a class which is independent in the project. These classes in my project could be working as a Data Pool, as a Resource Manager or just as a independent part with private constructor.

I worked with my generic singleton template mentioned in the History part of this tip, but several replies gave me another idea about how to use singleton in C# project.

Several Singleton Pattern

Mike75 proposed an article "Implementing the Singleton Pattern in C#" which listed 5 useful ways of implementing the singleton pattern. What is a useful singleton pattern? At least, it should be thread-safe - only one instance should only be created once in the whole life of the program.

C#
public sealed class Singleton
{
    private static Singleton instance = null;
    private static readonly object padlock = new object();

    Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            lock (padlock)
            {
                if (instance == null)
                {
                    instance = new Singleton();
                }
                return instance;
            }
        }
    }
} 

Above is a very simple thread-safe singleton class. It seems all good, it prevented from being created by two or more threads. But lock is acquired every time a new thread requires the instance.

Think about my generic singleton template, it used a version named double-check locking mentioned in the article "Implementing the Singleton Pattern in C#". It has several downsides, please read the original article to understand more.

C#
public sealed class Singleton
{
    private static readonly Singleton instance = new Singleton();

    // Explicit static constructor to tell C# compiler
    // not to mark type as beforefieldinit
    static Singleton()
    {
    }

    private Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            return instance;
        }
    }
} 

Above is a version which is better than the first version. But it's also its fatal convenient. Here is the explanation from the original article:

Static constructors in C# are specified to execute only when an instance of the class is created or a static member is referenced, and to execute only once per AppDomain. Given that this check for the type being newly constructed needs to be executed whatever else happens, it will be faster than adding extra checking as in the previous examples. However:

  • It's not as lazy as the other implementations. In particular, if you have static members other than Instance, the first reference to those members will involve creating the instance. This is corrected in the next implementation.
  • There are complications if one static constructor invokes another which invokes the first again. Look in the .NET specifications (currently section 9.5.3 of partition II) for more details about the exact nature of type initializers - they're unlikely to bite you, but it's worth being aware of the consequences of static constructors which refer to each other in a cycle.
  • The laziness of type initializers is only guaranteed by .NET when the type isn't marked with a special flag called beforefieldinit. Unfortunately, the C# compiler (as provided in the .NET 1.1 runtime, at least) marks all types which don't have a static constructor (i.e. a block which looks like a constructor but is marked static) as beforefieldinit.
C#
public sealed class Singleton
{
    private Singleton()
    {
    }

    public static Singleton Instance { get { return Nested.instance; } }
        
    private class Nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static Nested()
        {
        }

        internal static readonly Singleton instance = new Singleton();
    }
} 

Here, instantiation is triggered by the first reference to the static member of the nested class, which only occurs in Instance. This means the implementation is fully lazy, but has all the performance benefits of the previous ones. Note that although nested classes have access to the enclosing class's private members, the reverse is not true, hence the need for instance to be internal here. That doesn't raise any other problems, though, as the class itself is private. The code is a bit more complicated in order to make the instantiation lazy, however.

C#
public sealed class Singleton
{
    private static readonly Lazy<Singleton> lazy =
        new Lazy<Singleton>(() => new Singleton());
    
    public static Singleton Instance { get { return lazy.Value; } }

    private Singleton()
    {
    }
} 

Using .NET 4's Lazy<T> type is a most suggested method to construct a singleton class. Many replies suggested me to use Lazy<T>. Just take a rest and see its MSDN's definition.

Using the Code

What can we do with singleton pattern, what should we pay attention to when we use it. To be continued...

History

In my projects, singleton is often used for data pool management or a data service management. And this class conserves data shared by the whole application. Any other class or function shouldn't be able to access the data source directly. A singleton class is very useful if we want to isolate the data pool from others.

The generic singleton template facilitates you to define a singleton class. The code below shows the generic singleton template:

C#
public static class Singleton<T> where T : class
{
    static volatile T _instance;
    static object _lock = new object();
 
    static Singleton()
    { }
 
    public static T Instance
    {
        get
        {
            return (_instance != null) ? _instance : ResetAndGetInstance();
        } 
    }
 
    private static T ResetAndGetInstance()
    {
        lock (_lock)
        {
            if (_instance == null)
            {
                GetInstance();
            }
        }
        return _instance;
    }
 
    private static void GetInstance()
    {
        ConstructorInfo constructor = null;
        try
        {
            constructor = typeof(T).GetConstructor(BindingFlags.Instance | 
            BindingFlags.NonPublic, null, new Type[0], 
            null); // Binding flags exclude public constructors.
        }
        catch (Exception excep)
        {
            throw new SingletonException(excep);
        }
        if (constructor == null || constructor.IsAssembly)
        {
            throw new SingletonException(string.Format
            ("A private or protected constructor is missing 
            for '{0}'.", typeof(T).Name));
        }
        _instance = (T)constructor.Invoke(null);
    }
}  

The code below shows how to use this template to create a singleton class. It presents a data pool that can be used for preventing the data source from being used disorderly by the outside class.

C#
public class DataPool
{
    static object _syncRoot = new object();
    volatile List<DataUnit> _datas = new List<DataUnit>();

    private DataPool()
    {
    }

    public List<DataUnit> GetNewData(DateTime oldDt)
    {
        lock (_syncRoot)
        {
            var newDu = _datas.Where(p => p.DateTime > oldDt);
            if (newDu != null && newDu.Count() > 0)
                return newDu.ToList();
            else
                return null;
        }
    }

    public List<DataUnit> GetAllDatas()
    {
        lock (_syncRoot)
        {
            List<DataUnit> history = new List<DataUnit>();
            foreach (var item in _datas)
            {
                history.Add(new DataUnit()
                {
                    DateTime = item.DateTime,
                    Message = item.Message,
                    Sender = item.Sender
                });
            }
            return history;
        }
    }

    public void AddData(string message, string sender)
    {
        lock (_syncRoot)
        {
            _datas.Add(new DataUnit()
            {
                DateTime = DateTime.Now,
                Message = message,
                Sender = sender
            });
        }
    }

    public static DataPool Instance()
    {
        return Singleton<DataPool>.Instance;
    }
}

For calling this singleton data pool (getting instance of this singleton class), you just need to call the static method Instance().

C#
var newMessages = DataPool.Instance().GetNewData(_maxDateTime);  

Points of Interest

I'm not sure if this is the best way to define a singleton class, but it's really useful and efficient.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
France France
A foolish 18 years old boy
Just got an Microsoft C# Specialist Certification. Objectif of this year : MCSD

Comments and Discussions

 
SuggestionSo many to say Pin
mike7520-Dec-13 0:22
mike7520-Dec-13 0:22 
GeneralRe: So many to say Pin
comiscience20-Dec-13 1:03
comiscience20-Dec-13 1:03 
GeneralRe: So many to say Pin
mike7520-Dec-13 2:48
mike7520-Dec-13 2:48 
GeneralRe: So many to say Pin
comiscience20-Dec-13 3:12
comiscience20-Dec-13 3:12 
GeneralRe: So many to say Pin
mike7520-Dec-13 3:58
mike7520-Dec-13 3:58 
GeneralRe: So many to say Pin
comiscience20-Dec-13 4:21
comiscience20-Dec-13 4:21 
GeneralRe: So many to say Pin
mike7520-Dec-13 5:05
mike7520-Dec-13 5:05 
GeneralRe: So many to say Pin
comiscience20-Dec-13 2:37
comiscience20-Dec-13 2:37 
GeneralThoughts Pin
PIEBALDconsult13-Dec-13 8:56
mvePIEBALDconsult13-Dec-13 8:56 
GeneralRe: Thoughts Pin
comiscience15-Dec-13 21:12
comiscience15-Dec-13 21:12 
QuestionI suggest a different approach Pin
Brien Givens13-Dec-13 6:34
Brien Givens13-Dec-13 6:34 
GeneralRe: I suggest a different approach Pin
PIEBALDconsult13-Dec-13 8:51
mvePIEBALDconsult13-Dec-13 8:51 
AnswerRe: I suggest a different approach Pin
comiscience15-Dec-13 21:27
comiscience15-Dec-13 21:27 
GeneralRe: I suggest a different approach Pin
Brien Givens16-Dec-13 5:49
Brien Givens16-Dec-13 5:49 
1. There's no reason why you can't use a private constructor for a singleton. I left it as a public constructor since that's what you used in your article. You choice of accessibility level should be private -> protected internal -> internal -> protected -> public, in that order. If in doubt, start with private and move to the right until your code compiles.

2. I was referring to your use of volatile for the instance placeholder. Your singleton's properties can be modified by more than one thread, but its placeholder will only ever be null or contain the single instance, and therefore isn't volatile. The volatile keyword indicates that a field might be modified by multiple threads that are executing at the same time (i.e. concurrently). Whenever you lock an object (or its parent container), you prevent concurrent modification and therefore its placeholder (e.g. _datas) is not volatile. Concurrent means two or more threads modifying an object at the same time. Actually, it's a bit more complicated than that, but it's not a terrible way of thinking about it. If you do end up in a scenario where you want to enable concurrent thread access to an object, then you need to use a thread safe collection.

3. Locking the singleton usually works quite well. It prevents any other threads from concurrently modifying any of its properties. You can also lock an object-type property (generally a collection such as your _datas List) of the singleton. This prevents other threads from concurrently modifying that specific object - they could still modify other properties of your singleton. A lock should be quick - if you have any resource-intensive operations inside a lock then you're doing it wrong. Adding items to a List isn't a resource-intensive operation, but sending an email (for example) is. Whenever you're considering adding an object-based property to a class for the specific purpose of using it as a lock object, you're probably doing it wrong. If you're using a lock to prevent concurrent thread access to an object-based property of a class, then lock that object. If your lock is going to protect two or more object-based properties then you may be able to get away with locking them separately (i.e. nested locks), but you're probably going to be better off creating a new class which contains the two objects and then locking your instance of that class. If you really want to use nested locks, you need to be absolutely sure you understand how that works and avoid deadlocks.

The need for volatile with singletons is actually implementation-specific. It has to do with Double-checked locking.

Here's a quick and dirty example which proves that .NET handles the singleton properly:

<%@ webhandler class="CodeProject.WebHandler" language="C#" %>

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;

namespace CodeProject {

public class WebHandler : IHttpHandler {

  private HttpContext _Context;
  public bool IsReusable { get { return true; } }

  public void ProcessRequest(HttpContext context) {

    DataPool instance = DataPool.Instance;
    Thread t1 = new Thread(() => instance.LongLock(context));
    t1.Start();
    Thread.Sleep(1); // forces t1 before t2
    Thread t2 = new Thread(() => instance.JustIncrement(context));
    t2.Start();
    Thread.Sleep(1000);

  }

}

public class DataPool
{

    private static readonly Lazy<DataPool> _Instance =
        new Lazy<DataPool>( () => new DataPool(), LazyThreadSafetyMode.ExecutionAndPublication );

    private List<int> _datas = new List<int>();

    private int _increment = 0;

    public static DataPool Instance
    {
        get { return _Instance.Value; }
    }

    public void LongLock(HttpContext context)
    {
        lock (_datas) {
          context.Response.Write("Starting Sleep, Increment = " + _increment + "<br>");
          Thread.Sleep(500);
          context.Response.Write("Sleep is over, Increment = " + _increment);
        }
    }

    public void JustIncrement(HttpContext context)
    {
        _increment++;
        context.Response.Write("Concurrent, Increment = " + _increment + "<br>");

    }

}

}


Output:

Starting Sleep, Increment = 0
Concurrent, Increment = 1
Sleep is over, Increment = 1

Refresh the browser:

Starting Sleep, Increment = 1
Concurrent, Increment = 2
Sleep is over, Increment = 2
GeneralRe: I suggest a different approach Pin
comiscience16-Dec-13 6:35
comiscience16-Dec-13 6:35 
GeneralRe: I suggest a different approach Pin
Brien Givens16-Dec-13 6:38
Brien Givens16-Dec-13 6:38 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.