Share via


.NET: Singleton Pattern

Introduction

The following provides the basics for working with the singleton pattern. To get a broader perspective see C# Singleton pattern usage article which discuss when and when not to use this pattern.

Singleton pattern creates a class which can have a single object throughout the application, so that whenever any other object tries to access the object of the class, it will access the same object always.

Base class to start with

namespace YourNamespace
{
    public sealed  class Singleton
    {
        private static  Singleton _instance;
        private Singleton() // Made default constructor as private
        {
        }
        /// <summary>
        /// Single Instance
        /// </summary>
        public static  Singleton Instance
        {
            get
            {
                lock (_instance)
                {
                    _instance = _instance ?? new  Singleton();
                    return _instance;
                }
            }
        }
 
        #region Rest of Implementation Logic
 
        //Add As many method as u want here as instance member.
        // No need to make them static.
 
        #endregion
    }
}

In the above code you can see I have intentionally made the constructor as private. This will make sure that the class cant be instantiated from outside. On the other hand, you also need to make a property which will return the static instance of the object present within the class itself. Hence the object will be shared between all the external entities.

Thread safe singleton

When targeting .NET Framework 4 or higher Lazy<T> class can be used which is available for .NET, .NET Core, .NET Standard, UWP and Xamarin Frameworks.

An easy base code sample below creates an incremental string e.g. REF 0001, REF 0002 and so forth. The idea is to have a unique token that depending on implementation might be good for one day or longer that in this case is used to have unique subject/title for an email so that a provider does not see it as spam and is not intended to defeat a mail provider.

using System;
using System.Collections.Generic;
using System.Linq;
 
namespace YourNamespace
{
    /// <summary>
    /// Thread safe singleton responsible for creating
    /// unique sequence for email subject.
    /// </summary>
    public sealed  class ReferenceIncrementer
    {
        private static  readonly Lazy<ReferenceIncrementer> Lazy =
            new Lazy<ReferenceIncrementer>(() =>
                new ReferenceIncrementer());
 
        public static  ReferenceIncrementer Instance => Lazy.Value;
 
        private List<int> _baseList = new  List<int>();
 
        /// <summary>
        /// Populate HashSet with random numbers.
        /// HastSet items are unique.
        /// </summary>
        private void  CreateList()
        {
            _baseList = new  List<int>();
 
            for (var index = 1; index < 9000; index++)
            {
                _baseList.Add(index);
            }
        }
        /// <summary>
        /// Return a left padded number prefix with REF: 0001
        /// .Any ask if there are any values when called.
        /// </summary>
        /// <returns></returns>
        public string  GetReferenceValue()
        {
            if (!_baseList.Any())
            {
                CreateList();
            }
 
            var number = _baseList.FirstOrDefault();
            _baseList.Remove(number);
 
            return $" REF: {number:D4}";
 
        }
 
        /// <summary>
        /// Instantiate List
        /// </summary>
        private ReferenceIncrementer()
        {
            CreateList();
        }
        /// <summary>
        /// Used to reset at a given time e.g. right before midnight,
        /// perhaps by a scheduled job.
        /// </summary>
        public void  Reset()
        {
            CreateList();
        }
    }
}

Usage

var referenceValue = ReferenceIncrementer.Instance.GetReferenceValue();

External resources

Implementing the Singleton pattern

See also

C# Singleton pattern usage