.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