How to create a perfect Singleton class in c#?

23,102

Solution 1

If you are using .NET4 the "perfect singleton" is often best achieved using System.Lazy.

See also this web page for a description of many different singleton patterns in C# and their various pros and cons.

Solution 2

public static Singleton GetInstance()
    {
        lock (typeof(Singleton))
        {
            instance = new Singleton();
        }
        return instance;
    }

You only need to create a new instance if the member instance is null. You seem to be doing it all the time.

Solution 3

I use such singleton and I do not have problems:

public sealed class Settings
{
    private static readonly Lazy<Settings> lazy =
    new Lazy<Settings>(() => new Settings());

    public static Settings Instance { get { return lazy.Value; } }

    private Settings()
    {
        _fileName = "Settings.ini";
    }
....
}

Solution 4

I've always used this generic base class for my singletons:

public class SingletonBase<T> where T : class
{
    static SingletonBase()
    {
    }

    public static readonly T Instance =
        typeof(T).InvokeMember(typeof(T).Name,
                                BindingFlags.CreateInstance |
                                BindingFlags.Instance |
                                BindingFlags.Public |
                                BindingFlags.NonPublic,
                                null, null, null) as T;
}

Solution 5

public sealed class Singleton
{
    public static readonly Singleton Instance =new Singleton();
    private Singleton(){}
}//end

this is the best SINGLETON I've ever seen.

it is simple but thread-safe without using locks.

you can also make the 'Instance' as a property with a '_instance' field.

Share:
23,102
fiberOptics
Author by

fiberOptics

learner

Updated on December 05, 2020

Comments

  • fiberOptics
    fiberOptics over 3 years

    I want to store some data with Singleton class. As far as I've studied, singleton class can be instantiated only for once. But it doesn't work for me. Can someone correct my code:

    public class MvcApplication : System.Web.HttpApplication
        {
            Singleton clientsessionidinstance = Singleton.GetInstance();
            public static void RegisterGlobalFilters(GlobalFilterCollection filters)
            {
                filters.Add(new HandleErrorAttribute());
            }
    
    
            public static void RegisterRoutes(RouteCollection routes)
            {
                routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
                routes.MapRoute(
                    "Default", // Route name
                    "{controller}/{action}/{id}", // URL with parameters
                    new { controller = "Home", action = "Index", id = UrlParameter.Optional },
                    new string[] { "MVCPrj.Controllers" }
                );
            }
    
            protected void Application_Start()
            {
                AreaRegistration.RegisterAllAreas();
    
                RegisterGlobalFilters(GlobalFilters.Filters);
                RegisterRoutes(RouteTable.Routes);
    
                LOGICcLASSES.Logic.Auth ca = new LOGICcLASSES.Logic.Auth();
                clientsessionidinstance = Singleton.GetInstance();
                clientsessionidinstance.ClientSessionID = ca.Login(new LOGICcLASSES.Entities.ClientAuthentication()
                {
                    IP = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"],
                    UserName = ConfigurationManager.AppSettings["ClientUserName"],
                    Password = ConfigurationManager.AppSettings["ClientPassword"]
                });
            }
    
            protected void Application_AcquireRequestState(object sender, EventArgs e)
            {
                if (System.Web.HttpContext.Current.Session != null)
                {
                    if (!string.IsNullOrEmpty(clientsessionidinstance.ClientSessionID))
                    {
                        CurrentUserSession.Store<string>("ClientSessionID", clientsessionidinstance.ClientSessionID);
                    }
                }
            }
        }  
    

    So the goal is this, @ Application_Start I have to log in an account. Then I should save the return string on HttpContext.Current.Session.
    Unfortunately I can't access the HttpContext.Current.Session inside Application_Start but it is possible on Application_AcquireRequestState.
    I can use a variable that will hold the returned string and then use its value inside the Application_AcquireRequestState, but the big problem is this, the page loads? twice, so if I will use a variable, it will become null at the second load but Application_Start is still initiated once.
    So I came up using a Singleton class, but still I get null values on second load.

    Singleton class:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    
    namespace MVCPrj.Areas.WebPage.Logic
    {
        public class Singleton
        {
            private static Singleton instance;
    
            private Singleton() { }
    
            public static Singleton GetInstance()
            {
                lock (typeof(Singleton))
                {
                    instance = new Singleton();
                }
                return instance;
            }
    
            private string _ClientSessionID;
            public string ClientSessionID
            {
                get { return _ClientSessionID; }
                set { _ClientSessionID = value; }
            }
        }
    }  
    

    EDIT

    This code works for me after reading Singleton

    public class Singleton
    {
        private static readonly object _mutex = new object();
        private static volatile Singleton _instance = null;
        private Singleton() { }
    
        public static Singleton Instance
        {
            get
            {
                if (_instance == null)
                {
                    lock (_mutex)
                    {
                        if (_instance == null)
                        {
                            _instance = new Singleton();
                        }
                    }
                }
                return _instance;
            }
        }
    
        private string _ClientSessionID;
        public string ClientSessionID
        {
            get { return _ClientSessionID; }
            set { _ClientSessionID = value; }
        }
    }