Click here to Skip to main content
Click here to Skip to main content

Tagged as

Thinking in Singleton instead of A Useful Generic Singleton Template

, 13 Dec 2013 CPOL
Rate this:
Please Sign up or sign in to vote.
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.

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.

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.
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.

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:

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.

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().

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)

Share

About the Author

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

Comments and Discussions

 
QuestionSingleton Pattern Example PinmemberDeveloper Hemu Patel8-Aug-14 5:15 
SuggestionSo many to say Pinmembermike7520-Dec-13 1:22 
GeneralRe: So many to say Pinprofessionalcomiscience20-Dec-13 2:03 
GeneralRe: So many to say Pinmembermike7520-Dec-13 3:48 
GeneralRe: So many to say Pinprofessionalcomiscience20-Dec-13 4:12 
GeneralRe: So many to say Pinmembermike7520-Dec-13 4:58 
GeneralRe: So many to say Pinprofessionalcomiscience20-Dec-13 5:21 
GeneralRe: So many to say Pinmembermike7520-Dec-13 6:05 
GeneralRe: So many to say Pinprofessionalcomiscience20-Dec-13 3:37 
GeneralThoughts PinprofessionalPIEBALDconsult13-Dec-13 9:56 
GeneralRe: Thoughts Pinprofessionalcomiscience15-Dec-13 22:12 
QuestionI suggest a different approach Pinmemberic3b3rg13-Dec-13 7:34 
GeneralRe: I suggest a different approach PinprofessionalPIEBALDconsult13-Dec-13 9:51 
AnswerRe: I suggest a different approach [modified] Pinprofessionalcomiscience15-Dec-13 22:27 
GeneralRe: I suggest a different approach PinmemberBrien Givens16-Dec-13 6:49 
GeneralRe: I suggest a different approach Pinprofessionalcomiscience16-Dec-13 7:35 
GeneralRe: I suggest a different approach PinmemberBrien Givens16-Dec-13 7:38 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.1411023.1 | Last Updated 13 Dec 2013
Article Copyright 2013 by comiscience
Everything else Copyright © CodeProject, 1999-2014
Layout: fixed | fluid