Back to: Design Patterns in C# With Real-Time Examples
Why is Singleton Class Sealed in C#?
In this article, I will discuss Why Singleton Class Sealed in C# with Examples. Please read our previous article discussing the Singleton Design Pattern in C# with Examples. At the end of this article, you will understand why we need to use the sealed keyword in the Singleton class, as we already have a private constructor, which will restrict the class for further inheritance.
Why Singleton Design Pattern?
As we already discussed, we need to use the Singleton Design Pattern in C# to ensure that only one instance of a particular class is available at any given point in time for the entire application.
Why is Singleton Class Sealed in C#?
In C#, it is common practice to declare Singleton classes as “sealed” to prevent them from being inherited and ensure that only one class instance can exist. Sealing a class means it cannot be inherited by other classes, making it impossible for anyone to create a subclass and potentially introduce multiple instances of the Singleton.
Let us understand Why the Singleton Class is Sealed in C# with an example. First, create the Singleton class without using the sealed keyword. Then, create another class named DerivedSingleton and Inherit the DerivedSingleton from the singleton class, as shown below.
using System; namespace SingletonDemo { public class Singleton { //This variable value will be increment by 1 each time the object of the class is created private static int Counter = 0; //This variable is going to store the Singleton Instance private static Singleton Instance = null; //The following Static Method is going to return the Singleton Instance public static Singleton GetInstance() { //If the variable instance is null, then create the Singleton instance //else return the already created singleton instance //This version is not thread-safe if (Instance == null) { Instance = new Singleton(); } //Return the Singleton Instance return Instance; } //Constructor is Private means, from outside the class we cannot create an instance of this class private Singleton() { //Each Time the Constructor is called, increment the Counter value by 1 Counter++; Console.WriteLine("Counter Value " + Counter.ToString()); } //The following can be accessed from outside of the class by using the Singleton Instance public void PrintDetails(string message) { Console.WriteLine(message); } } public class DerivedSingleton : Singleton { } }
At the moment, you will get the following compilation error. Error CS0122 ‘Singleton.Singleton()’ is inaccessible due to its protection level
The above error is because of our private constructor in the Singleton class. You might be thinking that as we have a private constructor within the class, it is impossible to derive this class, so why do we need to apply the sealed keyword to the Singleton class?
Let’s move the DerivedSingleton class inside the Singleton class. When we move the DerivedSingleton class within the main Singleton class, it becomes a nested or child class of the main Singleton class, as shown below.
using System; namespace SingletonDemo { public class Singleton { //This variable value will be increment by 1 each time the object of the class is created private static int Counter = 0; //This variable is going to store the Singleton Instance private static Singleton Instance = null; //The following Static Method is going to return the Singleton Instance public static Singleton GetInstance() { //If the variable instance is null, then create the Singleton instance //else return the already created singleton instance //This version is not thread-safe if (Instance == null) { Instance = new Singleton(); } //Return the Singleton Instance return Instance; } //Constructor is Private means, from outside the class we cannot create an instance of this class //But within the class, we can create an instance private Singleton() { //Each Time the Constructor is called, increment the Counter value by 1 Counter++; Console.WriteLine("Counter Value " + Counter.ToString()); } //The following can be accessed from outside of the class by using the Singleton Instance public void PrintDetails(string message) { Console.WriteLine(message); } //Creating Nested Derived Class inheriting from Singleton Class public class DerivedSingleton : Singleton { } } }
What is a Nested Class in C#?
Whenever we define a class within another class in C#, the inner class is called a nested or child class. Now, if we compile the program, we will not get any errors. Let us modify the main method of the program class to access the nested class, as shown below.
using System; namespace SingletonDemo { class Program { static void Main(string[] args) { //Call the GetInstance static method to get the Singleton Instance Singleton fromTeachaer = Singleton.GetInstance(); fromTeachaer.PrintDetails("From Teacher"); //Call the GetInstance static method to get the Singleton Instance Singleton fromStudent = Singleton.GetInstance(); fromStudent.PrintDetails("From Student"); //Instantiating singleton from a Derived class. //This violates Singleton Pattern Pattern. Singleton.DerivedSingleton derivedObj = new Singleton.DerivedSingleton(); derivedObj.PrintDetails("From Derived"); Console.ReadLine(); } } }
If you run the application, you will see the following output.
The above output clearly shows that the counter value has incremented to 2, proving that the private constructor executed twice, creating multiple instances of the singleton class. So, by removing the sealed keyword, we can inherit the singleton class and create multiple objects of the singleton class. This violates singleton design principles. Let’s make the Singleton class as sealed, as shown below, and then compile the program and see what happens.
using System; namespace SingletonDemo { public sealed class Singleton { //This variable value will be increment by 1 each time the object of the class is created private static int Counter = 0; //This variable is going to store the Singleton Instance private static Singleton Instance = null; //The following Static Method is going to return the Singleton Instance public static Singleton GetInstance() { //If the variable instance is null, then create the Singleton instance //else return the already created singleton instance //This version is not thread-safe if (Instance == null) { Instance = new Singleton(); } //Return the Singleton Instance return Instance; } //Constructor is Private means, from outside the class we cannot create an instance of this class //But within the class, we can create an instance private Singleton() { //Each Time the Constructor is called, increment the Counter value by 1 Counter++; Console.WriteLine("Counter Value " + Counter.ToString()); } //The following can be accessed from outside of the class by using the Singleton Instance public void PrintDetails(string message) { Console.WriteLine(message); } //Creating Nested Derived Class inheriting from Singleton Class public class DerivedSingleton : Singleton { } } }
We got an error when compiling the program, saying we could not derive a sealed class. So, from this point, we conclude that the private constructor in C# will help us only prevent any external instantiations of the class, and the sealed keyword will prevent the class inheritances.
The above Singleton implementation is not thread-safe. The way we implement the Singleton class allows two different threads simultaneously to evaluate the condition if (instance == null) and find it to be true. They both create instances that violate the singleton design pattern.
Why are Singleton classes often sealed in C#?
Here are a few reasons why Singleton classes are often sealed in C#:
- Preserving Singleton Semantics: The Singleton pattern is designed to ensure that there is only one instance of a class throughout the lifetime of an application. By sealing the class, you prevent potential issues that might arise from someone attempting to inherit from the Singleton class and create their own instances.
- Preventing Subclassing: If a Singleton class is not sealed, it can be subclassed. Subclassing can lead to situations where multiple class instances are created, violating the Singleton pattern’s intent. Sealing the class prevents this scenario.
- Enforcing Design Intent: Sealing the Singleton class enforces the design intent of the Singleton pattern, making it clear to other developers that the class should only ever have one instance. It communicates the class’s intended usage and behavior.
By declaring the Singleton class sealed, you ensure that it cannot be inherited and the Singleton pattern is enforced. This makes it easier for developers to work with the class, knowing that its behavior is consistent and that there will be only one instance throughout the application’s lifetime.
In the next article, I will discuss How to Handle Thread Safety in the Singleton Class, as the current version of singleton implementation can create multiple instances of the singleton class in multi-threaded environments. I explain Why the Singleton Class Sealed in C# in this article with Examples. I hope this article will help you to understand Why the Singleton Class is Sealed in C# with Examples.
About the Author: Pranaya Rout
Pranaya Rout has published more than 3,000 articles in his 11-year career. Pranaya Rout has very good experience with Microsoft Technologies, Including C#, VB, ASP.NET MVC, ASP.NET Web API, EF, EF Core, ADO.NET, LINQ, SQL Server, MYSQL, Oracle, ASP.NET Core, Cloud Computing, Microservices, Design Patterns and still learning new technologies.
Thank you. Well explained.
Thank you, excellent explanation!
Awesome
awesome tutorial, thank you
Nice, Thank you.
Well explained. Thanks team dotnettutorials and to the author of this course.