When to use Singleton
I’ve been using Dependency Injection (DI) engines for a while now and I’m always poking my Team Mates to configure the scope of the dependencies to most appropriate setting for each given case.
By using Singleton scoped dependencies, it’s ensured that the memory needed for the application to run is not duplicated among several instances of a class.
As such, singletons should be used for:
- Stateless classes: classes that do not store any state on it’s internal variables;
- Global single instance: Instead of using
staticclasses and methods, the singleton scope ensures a controlled initialization of the class. An example of this condition is In-Memory Cache technique.
- Shared access to a single resource: if there is some resource that is unique and it’s access is controlled by a class, than this class should be a singleton and should be responsible to manage the concurrency for accessing the resource.
.NET Core Singleton Scope
The .NET Core framework offers a simple Dependency Injection engine called
ServiceCollection that supports several scopes by default:
AddTransient()will create an instance each time it is requested;
AddScoped()will create an instance for each request (e.g. a single instance for each HTTP request);
AddSingleton()will create an instance of the class upon the first request and reuse that instance among subsequent requests.
Let«’s consider an application that has an
ImageStoreclass that loads images from a given location and keeps them in memory for future use.
Now, suppose this
ImageStore is referenced by two different classes say
By configuring the DI engine to scope
ImageStore as a Singleton, it will ensure that i) the same instance is reused among all the dependencies that use
ImageStore and ii) the images stored on
imageMap will not be duplicated (or n-uplicated) among several instances of
Now, to see the difference, consider the following .NET Core code:
This will create two instances of
ImageStore, one for each request to
GetService<ImageStore> and, thus, allocating 12MB (2 x 10 x 601KB) in the heap.
By changing the scope to Singleton as in:
ImageStore is created and initialized only once and the same instance will be returned for every call to
GetService<ImageStore> which will save the duplication on the heap: