Singleton Class in C#
Introduction
According to the singleton design pattern, a single object may only be created using a single class instance in C#. It enables a single point for getting to that instance and ensures it will only ever be one instance of the class across the whole program.
Syntax:
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton ();
private Singleton ()
{
}
public static Singleton Instance
{
get
{
return instance;
}
}
}
- The class can't be inherited thanks to the sealed keyword.
- A single static instance of the class is stored in the private static read-only field instance, which is eagerly initialized.
- The class cannot be externally instantiated, thanks to the private constructor.
- Accessing the single instance of the class is made possible via the public static property or method Instance.
- The singleton class can have additional members and functions as necessary.
Example:
using System;
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton ();
private Singleton ()
{
}
public static Singleton Instance
{
get
{
return instance;
}
}
public void PrintMessage(string message)
{
Console.WriteLine("Singleton Instance: " + message);
}
}
public class Program
{
public static void Main ()
{
Singleton s1 = Singleton.Instance;
Singleton s2 = Singleton.Instance;
s1. PrintMessage("Welcome");
Console.WriteLine(s1 == s2);
}
}
This syntax
- The single instance of the class is stored in a private static field called instance for the Singleton class.
- A private static read-only object used for thread synchronization is the lockObject field.
- The singleton class cannot be created externally thanks to the private constructor.
- Access to the singleton instance is made possible through the Instance attribute.
- A double-check locking method is utilized inside the get accessor of the Instance property to guarantee thread safety while the instance is being created.
To avoid needless locking if the instance has already been generated, the initial check (if (instance == null)) determines whether the instance is already null.
The lock statement is used to acquire a lock if the instance is null, ensuring that only one thread may access the code block contained within the lock at once.
In order to stop another thread from generating a duplicate instance while waiting for the lock, a second check (if (instance == null)) is made inside the lock to make sure the instance is still null.
Instance = new Singleton (); is used to ensure instance if it is still null.
The constructed instance is then returned through the Instance property.
Output:
![Singleton Class in C#](https://static.tutorialandexample.com/csharp/singleton-class-in-csharp1.png)
Singleton class forms in C#
Implementing a singleton class in C# might take many shapes or guises. Listed below are a few typical forms:
1. Eager initialization
- The singleton class instance is eagerly constructed in this way during class loading.
- Since the instance is generated before any thread can access it, the singleton's thread safety is ensured.
public sealed class Singleton
{
private static readonly Singleton instance = new Singleton ();
private Singleton () {}
public static Singleton Instance => instance;
}
2. Lazy initialization
- This arrangement generates the singleton class object passively or at accessing time.
- By waiting until an instance is needed, it offers superior performance.
using System;
public sealed class Singleton
{
private static readonly Lazy<Singleton> lazyInstance = new Lazy<Singleton> (() => new Singleton ());
private Singleton ()
{
}
public static Singleton Instance => lazyInstance.Value;
}
3. Initialization using double-check locking that is thread-safe
- While permitting lazy initialization, this style provides thread safety.
- Access to the instance creation code is synchronized via a lock statement.
using System;
public sealed class Singleton
{
private static Singleton instance;
private static readonly object lockObject = new object ();
private Singleton ()
{
}
public static Singleton Instance
{
get
{
if (instance == null)
{
lock (lockObject)
{
if (instance == null)
{
instance = new Singleton ();
}
}
}
return instance;
}
}
}
Purpose:
- Global Access: A singleton offers a single point of access to its instance available anywhere in the world. It might be helpful when you need to use a shared resource or keep track of a centralized state that can be accessed from other application areas.
- Resource management: Singleton classes may be used to manage resources like database connections, file systems, and network connections that should only have a single instance. You may prevent resource conflicts and effectively manage resource allocation and deallocation by assuring a single instance.
- Configuration Settings: Singleton classes are frequently used to maintain configuration parameters for the whole program. You may load the configuration only once and distribute it among other application components using a singleton.
- Thread Safety: Singleton classes may be built to address thread-safety issues, guaranteeing that even in multi-threaded settings, only one instance is produced. Race situations and concurrency concerns may be avoided as a result.