Singleton Pattern in C#: Definition, Examples, Pros & Cons
The Singleton pattern in C# ensures that a class has only one instance and provides a global access point to that instance.
The Singleton pattern is a creational design pattern used when exactly one object should exist throughout the application lifecycle. It restricts direct object instantiation by making the constructor private and exposing a single shared instance. In C#, Singleton is commonly used for configuration management, logging systems, caching, and database connection managers. Thread safety is an important consideration in multi-threaded applications, and modern implementations often use Lazy<T> or locking mechanisms. The pattern helps centralize shared resources and maintain consistent application state.
Why We Use Singleton Pattern in C#?
We use the Singleton pattern to ensure controlled access to a single shared instance across the application. It reduces unnecessary object creation and provides a centralized place for shared functionality or state management. It is also useful when coordinating actions across different parts of a system.
When to Use Singleton Pattern in C#?
Use this pattern when only one instance of a class should exist, such as loggers, configuration managers, caches, or application-wide services. It is appropriate when multiple instances could cause inconsistent behavior or unnecessary resource usage. Singleton is also useful when global access to a shared object is required.
Example Use Cases with C# Code
1. Basic Singleton Implementation
public sealed class Singleton
{
private static readonly Singleton _instance = new Singleton();
// Private constructor prevents external instantiation
private Singleton()
{
}
public static Singleton Instance
{
get { return _instance; }
}
public void ShowMessage()
{
Console.WriteLine("Singleton Instance Called");
}
}
Usage:
Singleton.Instance.ShowMessage();
2. Thread-Safe Singleton with Lock
public sealed class ThreadSafeSingleton
{
private static ThreadSafeSingleton _instance;
private static readonly object _lock = new object();
private ThreadSafeSingleton()
{
}
public static ThreadSafeSingleton Instance
{
get
{
lock (_lock)
{
if (_instance == null)
{
_instance = new ThreadSafeSingleton();
}
return _instance;
}
}
}
}
3. Modern Singleton with Lazy<T>
using System;
public sealed class Logger
{
private static readonly Lazy<Logger> _instance =
new Lazy<Logger>(() => new Logger());
private Logger()
{
}
public static Logger Instance => _instance.Value;
public void Log(string message)
{
Console.WriteLine($"Log: {message}");
}
}
Usage:
Logger.Instance.Log("Application started");
Advantages of Singleton Pattern in C#
• Ensures a single shared instance
• Provides global access to the instance
• Reduces memory usage for shared resources
• Centralizes configuration and state management
• Can improve performance by avoiding repeated instantiation
Disadvantages of Singleton Pattern in C#
• Introduces global state, which can increase coupling
• Makes unit testing more difficult
• Can violate the Single Responsibility Principle
• Thread safety adds implementation complexity
• Overuse may reduce flexibility and scalability
Comparison with Similar Patterns
| Pattern | Purpose | Key Difference | Use Case |
|---|---|---|---|
| Singleton | Ensure only one instance exists | Controls instance count globally | Logging, caching, configuration |
| Static Class | Provide utility methods | No instance can be created | Helper and utility functions |
| Factory Method | Create objects through subclasses | Focuses on object creation flexibility | Framework extensibility |
| Monostate | Share state across instances | Allows multiple instances with shared state | Shared application settings |