How to Create Singleton in C#: Simple Guide
To create a
singleton in C#, define a class with a private constructor and a static readonly instance property that returns the single object. Use lazy initialization with Lazy<T> for thread safety and to ensure only one instance is created.Syntax
The singleton pattern in C# uses a private constructor to prevent external instantiation, a private static readonly field to hold the single instance, and a public static property to provide global access to that instance.
- private constructor: stops creating new objects from outside.
- static readonly instance: holds the single object.
- public static property: returns the single instance.
- Lazy<T>: ensures thread-safe, lazy creation.
csharp
public sealed class Singleton { private static readonly Lazy<Singleton> instance = new Lazy<Singleton>(() => new Singleton()); private Singleton() { // Private constructor prevents external instantiation } public static Singleton Instance { get { return instance.Value; } } }
Example
This example shows how to use the singleton class. It prints the same instance's hash code twice, proving only one object exists.
csharp
using System; public sealed class Singleton { private static readonly Lazy<Singleton> instance = new Lazy<Singleton>(() => new Singleton()); private Singleton() { // Private constructor } public static Singleton Instance => instance.Value; public void ShowMessage() { Console.WriteLine("Singleton instance hash code: " + this.GetHashCode()); } } class Program { static void Main() { Singleton s1 = Singleton.Instance; Singleton s2 = Singleton.Instance; s1.ShowMessage(); s2.ShowMessage(); Console.WriteLine("Are both instances equal? " + (s1 == s2)); } }
Output
Singleton instance hash code: 46104728
Singleton instance hash code: 46104728
Are both instances equal? True
Common Pitfalls
Common mistakes when creating singletons in C# include:
- Not making the constructor private, allowing multiple instances.
- Not handling thread safety, causing multiple instances in multithreaded apps.
- Using a public static field instead of a property, which is less flexible.
- Creating the instance eagerly without need, wasting resources.
Always use Lazy<T> or locks to ensure thread safety.
csharp
/* Wrong way: public constructor allows multiple instances */ public class WrongSingleton { public static WrongSingleton Instance = new WrongSingleton(); public WrongSingleton() { } } /* Right way: private constructor and Lazy<T> for thread safety */ public sealed class RightSingleton { private static readonly Lazy<RightSingleton> instance = new Lazy<RightSingleton>(() => new RightSingleton()); private RightSingleton() { } public static RightSingleton Instance => instance.Value; }
Quick Reference
Singleton Pattern Cheat Sheet:
- Class: sealed to prevent inheritance.
- Constructor: private to block external creation.
- Instance: static readonly Lazy<T> for lazy, thread-safe creation.
- Access: public static property returns the instance.
Key Takeaways
Use a private constructor to prevent creating multiple instances.
Use static readonly Lazy for thread-safe, lazy initialization.
Access the singleton instance via a public static property.
Avoid public constructors and non-thread-safe code to prevent bugs.
Singleton ensures only one instance exists during app lifetime.