Click here to Skip to main content
15,867,838 members
Articles / Desktop Programming / WPF

Thinking in Singleton instead of My Singleton in WPF

Rate me:
Please Sign up or sign in to vote.
5.00/5 (3 votes)
14 Dec 2013CPOL4 min read 22.8K   13   9
Here is my favourite singleton class which serves a class which has only 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 Code Project 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' 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 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

 
SuggestionWhy don't just use Lazy<T> ? Pin
Citiga15-Dec-13 23:54
Citiga15-Dec-13 23:54 
GeneralRe: Why don't just use Lazy<T> ? Pin
comiscience16-Dec-13 0:01
comiscience16-Dec-13 0:01 
QuestionYou don't need locks Pin
mikeward00115-Dec-13 2:55
mikeward00115-Dec-13 2:55 
AnswerRe: You don't need locks Pin
comiscience15-Dec-13 3:05
comiscience15-Dec-13 3:05 
AnswerYou are wrong Pin
FatCatProgrammer16-Dec-13 4:09
FatCatProgrammer16-Dec-13 4:09 
GeneralRe: You are wrong Pin
comiscience16-Dec-13 4:51
comiscience16-Dec-13 4:51 
GeneralRe: You are wrong Pin
FatCatProgrammer16-Dec-13 8:03
FatCatProgrammer16-Dec-13 8:03 
GeneralRe: Am I? Pin
mikeward0019-Mar-14 3:47
mikeward0019-Mar-14 3:47 
GeneralMy 5 Pin
Sperneder Patrick15-Dec-13 1:00
professionalSperneder Patrick15-Dec-13 1:00 
A very elegant solution!
I really like your approach of a generic singleton. Thumbs up! Smile | :)

Regards P.

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.