Use the Singleton design pattern to create classes of which only one instance can exist Design patterns are solutions to recurring problems and complexities in software design and are classified into three distinct categories: creational, structural, and behavioral. While creational patterns are used to create and manage the mechanism of creating instances of classes, structural patterns are those that are used to define the structure of types and their relationships — these help to realize the relationships among the entities. Behavioral design patterns are those that deal with object collaboration and delegation of responsibilities among them. The Singleton Design pattern is a creational design pattern that states that one and only one instance of a class can exist throughout the lifetime of an application. In this article, I will present an overview of the Singleton design pattern and show how we can implement it using the C# programming language. Should I use a static class or a Singleton class? A static class is one that can only have static members. You cannot inherit or instantiate a static class. Unlike static classes, Singleton classes can be inherited, can have base class, can be serialized and can implement interfaces. You can implement Dispose method in your Singleton class. So, static classes are much less flexible compared to Singleton classes. The choice between a Singleton class and a static class entirely depends on whether or not you need an instance for your class and the advantages that a Singleton class provides. Static classes can only have static members are these classes cannot be inherited — these classes are sealed implicitly. While static classes are a good choice for storing helper methods, you can use a Singleton class to build a state manager class that can manage state (application state, cache or session, etc.) in your application. Another advantage of a Singleton class is that it can be initialized lazily or asynchronously. You can’t do this with a static class — it is initialized when it is loaded in the memory. Implementing a Singleton class Well, let’s now dig into some code. The following code snippet illustrates a Singleton class. public class StateManager { private static StateManager instance; private StateManager() {} public static StateManager Instance { get { if (instance == null) { instance = new StateManager(); } return instance; } } } Note how the object of the StateManager class has been created. The static property Instance can be used to retrieve a reference to the instance of the StateManager class. The StateManager class is sealed to prevent inheritance and it has a private constructor so that no instance of it can be created. OK, but what about thread safety? The following code listing shows a modified version of the StateManager class that has thread safety implemented. public sealed class StateManager { private static volatile StateManager instance; private static object lockObj = new Object(); private StateManager() {} public static StateManager Instance { get { if (instance == null) { lock (lockObj) { if (instance == null) instance = new StateManager(); } } return instance; } } } The volatile keyword is used to ensure that the object is initialized prior to being accessed. This implementation is thread safe — a check is made to see if an instance of the StateManager class has been created prior to creating the instance. Note that instead of locking on the typeof(StateManager) you should lock on a static object that is private to the StateManager class. This ensures that the potential risks of performance issues and deadlocks are eliminated. The next version of our StateManager class implements lazy initialization using a nested class. public sealed class StateManager { private StateManager() { } public static StateManager Instance { get { return Nested.instance; } } private class Nested { static StateManager() { } internal static readonly StateManager instance = new StateManager(); } } You might not need full laziness in most cases unless your Singleton class needs to do some initialization that would be resource consuming and takes up a lot of time. Having said that I would prefer to use lazy initialization only if there are no resource consuming initialization operations needed in the class. Note that a static constructor is invoked when the class is instantiated or when a static member of the class is accessed.The explicit static constructor is used in the example earlier to inform the runtime not to mark the type (the StateManager class in this example) as beforefieldinit. Our final version of the StateManager class is even better – it leverages the System.Lazy type (available from .Net Framework 4) to make the laziness seamless and simple. public sealed class StateManager { private static readonly Lazy<StateManager> singleton = new Lazy<StateManager>(() => new StateManager()); public static StateManager Instance { get { return singleton.Value; } } private StateManager() { } } You can learn more on Singleton design pattern and how it can be implemented in C# from this MSDN article. Related content feature What is Rust? Safe, fast, and easy software development Unlike most programming languages, Rust doesn't make you choose between speed, safety, and ease of use. Find out how Rust delivers better code with fewer compromises, and a few downsides to consider before learning Rust. By Serdar Yegulalp Nov 20, 2024 11 mins Rust Programming Languages Software Development how-to Kotlin for Java developers: Classes and coroutines Kotlin was designed to bring more flexibility and flow to programming in the JVM. Here's an in-depth look at how Kotlin makes working with classes and objects easier and introduces coroutines to modernize concurrency. By Matthew Tyson Nov 20, 2024 9 mins Java Kotlin Programming Languages analysis Azure AI Foundry tools for changes in AI applications Microsoft’s launch of Azure AI Foundry at Ignite 2024 signals a welcome shift from chatbots to agents and to using AI for business process automation. By Simon Bisson Nov 20, 2024 7 mins Microsoft Azure Generative AI Development Tools news Microsoft unveils imaging APIs for Windows Copilot Runtime Generative AI-backed APIs will allow developers to build image super resolution, image segmentation, object erase, and OCR capabilities into Windows applications. By Paul Krill Nov 19, 2024 2 mins Generative AI APIs Development Libraries and Frameworks Resources Videos