Singleton vs Static Class
Singleton and Static classes can only have one instance available in memory, and both classes can be used to maintain the global state of an application, however, there are many differences between them. In this article, I explain what their differences are.
Singleton is one of the creational patterns from “Gang of Four” (GoF), and it ensures that a class only has one instance (restricting a class to instantiate its multiple objects), and provides a global point of access to it.
The Singleton pattern simply uses a private constructor and a static readonly instance variable that is lazily initialized. Thread safety is guaranteed by the compiler.
The code below demonstrates how a Singleton class works (the examples were created using a console application using .NET 6), and demonstrates that when the code is executed, the same instance of the class will be returned:
On lines 1 and 2, there are two variables that receive the instance of the Singleton class, and when compared, the result is that they are the same instance. Notice that this class has a private property (this is quite common to have in a Singleton class) and this property is static, and also has a method that returns the instance of the object. In the “Instance” method, it’s checked if the instance of the class was already created, and if it was, will return the created instance, otherwise, will create an instance, and the next time that this class is called will return the same created instance (and for that, a static method can be used). There are also other ways to implement singleton, if you are interested in knowing more about it, check the article Implementing the Singleton Pattern in C# by C# in Depth.
Singleton is also one of the service lifetimes that can be used with Microsoft Dependency Injection Container. When using Singleton, the Services are created once for the lifetime of the application (it uses the same instance for the whole application). If you want to read more about Dependency Injection (DI) and Service Lifetimes in .NET, check the article in the blog by clicking here. This is how you can configure a Singleton service with DI in .NET:
Static is a modifier keyword (a language feature), which can be used to define a class/methods/fields/properties as static. A Static class cannot be instantiated, which means that, unlike a non-static class, you can not use the operator
new to create a variable of the class type, instead, in order to use a static class you can access the class members directly. Also, a static class is a sealed class, therefore does not support inheritance, and static methods do not allow overriding.
.NET brings some static classes such as “System.Math”, “System.Convert”, and others, and when you need to use a method from the Math class for example, you can directly call the method directly without needing to instantiate the class, like this:
In the following code, there is an example of how to create and use a static class (the class TemperatureConverter is from Microsoft Documentation). In C#, you can create a static class by using the keyword
On line 1 the static class is being called, the method to convert Celsius to Fahrenheit will be executed and the value will be printed in the console. On line 5, the static class is defined, and on line 7 there is a static method (note that all methods inside of a static class, must also be static).
It’s also possible to have a non-static class that has static methods, fields, properties or events. In the example below there is a non-static class with a static property. When the code is executed, the value “2” will be printed in the console:
That is because the property
static, which means that even if two non-static objects are created, it will keep the same state for the static property, even if multiple instances of the class are created.
Now if instead of having a static property, we use a normal property, the output of the following code will be that the number 1 will be printed twice:
Similarities between Singleton and Static
- Both Static and Singleton classes can have only one instance available in the memory.
- Both classes can be used for holding the global state of an application.
Differences between Singleton and Static
- A Singleton class supports interface implementation, while static classes cannot implement interfaces.
- A Singleton class supports inheritance, while a Static class is a sealed class, and therefore cannot be inherited.
- A Singleton class can inherit from other classes, while a Static class cannot (not even from other static classes).
- A Singleton class can be instantiated using the
newkeyword, while static can not be instantiated (static class can be used directly).
- Both Singleton and static are stored on the Heap memory, but static classes are stored in a special area of the Heap Memory called the High-Frequency Heap (Objects in High Frequency Heap are not garbage collected by GC, and hence static members are available throughout the application lifetime).
- A Singleton class can Dispose, while a static class can not.
- A Singleton class can have a constructor, while a static class can only have a private static parameterless constructor and cannot have instance constructors.
- A Static class has better performance since static methods are bonded on compile time.
- A Singleton class can be lazy loaded when needed, while static classes are always loaded. Static classes are loaded automatically by the .NET Framework common language runtime (CLR) when the program or namespace containing the class is loaded.
Static classes can be used when you need to implement some kind of utility classes that do not need many modifications, classes such as extension, helper, constant, etc. As Static classes don’t allow instantiation, there will be no duplicate objects, avoiding extra usage of memory.
Singleton classes can be used when only one instance of a particular class needs to be created, and then a simple global access to that instance is going to be provided for the entire application, for example when you have some service proxies, a Logger class, caching, database connections, etc.