Singleton Design Pattern ensures that a class has exactly one copy and provide a global access point to it
Real-life example:
- Logger
- One instance is preferred to avoid unintended consequences.
The class must be responsible for ensuring only one instance of itself exists.
public class Logger
{
    private static Logger? _instance; 
    /// <summary>
    /// Instance
    /// </summary>
    public static Logger Instance
    {
        get
        {
            if (_instance == null) //This is not thread safe. 
            {
                _instance = new Logger();
            }
            return _instance;
        }
    }
    protected Logger()
    {
    }
    /// <summary>
    /// Singleton Operation
    /// </summary>
    /// <param name="message"></param>
    public void Log(string message)
    {
        Console.WriteLine(message);
    }
}
Above code is not thread safe. If the instance is created by another thread, it will create another instance. 
To resolve thread safe issue, Lazy<T> can be used as below. 
public class LazyLogger
{
    //Lazy<T>
    private static readonly Lazy<LazyLogger> LazyLoggerInstance = 
                new Lazy<LazyLogger>(() => new LazyLogger());
    /// <summary>
    /// Instance
    /// </summary>
    public static LazyLogger Instance => LazyLoggerInstance.Value;
    protected LazyLogger()
    {
    }
    /// <summary>
    /// Singleton Operation
    /// </summary>
    /// <param name="message"></param>
    public void Log(string message)
    {
        Console.WriteLine(message);
    }
}
When to Use Singleton Pattern
More real world example
Outcome of Singleton Pattern