DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations

The Singleton Pattern in C#: An Absolute Beginner’s Tutorial

This article is yet another explanation and implementation of the singleton pattern. We will look at what is singleton pattern is and how to implement it in C#. This is no way the best and recommended way of implementing the singleton pattern in C#, but this article is intended to present the concept of singleton pattern to readers.

Rahul Rajat Singh user avatar by
Rahul Rajat Singh
·
Jan. 26, 16 · Tutorial
Like (2)
Save
Tweet
Share
22.33K Views

Join the DZone community and get the full member experience.

Join For Free

This article is yet another explanation and implementation of the singleton pattern. We will look at what is singleton pattern is and how to implement it in C#. This is no way the best and recommended way of implementing the singleton pattern in C#, but this article is intended to present the concept of singleton pattern to readers.

Background

Whenever we have a scenario in our application where:

  • A single instance of a class is required in the application and the class itself is able to enforce the single instance on itself. The rest of the system need not worry about managing the single instance.
  • This single instance class should be accessible by the complete system or most parts of the system.
  • This single instance subsystem should not be created and initialized unless it is required. (lazy initialization)

Let's see how we can have a class that will let the callers create only one single instance of it. The first thing we should ask ourselves is how are the instance of the classes created. The answer is by calling new for the class which in turn will call the constructor of the class. So, if we want the applications not to be able to create by number of instances, we should first restrict the access to the constructor (i.e. make the constructor private).

If we are making the constructor private, the next question we have is how will we be creating the instance of this class. Since the private constructor can still be called from the class itself, we can create an instance of this class inside the class itself. So, to do this we need to create a static method (static methods will not need callers to have an instance to be called) inside the class (i.e. GetInstancewhich will create an object of this class and return it to the applications).

Using the Code

Let's look at the class that is implementing the instance creation using the above discussed method and returning the instance to the caller.

public sealed class Singleton
{
    // A private constructor to restrict the object creation from outside
    private Singleton()
    {

    }

    // A private static instance of the same class
    private static Singleton instance = null;

    public static Singleton GetInstance()
    {
        // create the instance only if the instance is null
        if (instance == null)
        {
            instance = new Singleton();
        }

        // Otherwise return the already existing instance
        return instance;
    }
}

Now the above class will let the user create only one instance of this class i.e. singleton in the simplest of forms.

Hello Multi-Threading

There is a problem with this class: it is not thread safe. So to make it thread safe, we need to make sure that the instantiation code can be accessed only by a single thread at any given time. So, lets do that and introduce a lock in our class to guard the GetInstancecalls.

public sealed class Singleton
{
    // A private constructor to restrict the object creation from outside
    private Singleton()
    {

    }

    // A private static instance of the same class
    private static Singleton instance = null;
    private static readonly object _lock = new object();

    public static Singleton GetInstance()
    {
        lock (_lock)
        {
            // create the instance only if the instance is null
            if (instance == null)
            {
                instance = new Singleton();
            }

            // Otherwise return the already existing instance
            return instance;
        }
    }
}

Now the instance retrieval code can only be accessed by one single thread at any given time. Bu,t this incorporates a performance problem. Our idea was to not let multiple threads be able to create multiple instances, so we needed to guard the instance creation part in lock. What we have done instead is guarded the complete method with lock, which would mean that the lock will be acquired even when the instance has been created and it just needs to be returned. To circumvent this problem, we need to guard only the instance creation part under lock and not the instance return part.

public sealed class Singleton
{
    // A private constructor to restrict the object creation from outside
    private Singleton()
    {

    }

    // A private static instance of the same class
    private static Singleton instance = null;
    private static readonly object _lock = new object();

    public static Singleton GetInstance()
    {
        if (instance == null)
        {
            lock (_lock)
            {
                // create the instance only if the instance is null
                if (instance == null)
                {
                    instance = new Singleton();
                }
            }
        }

        // Otherwise return the already existing instance
        return instance;
    }
}

Now what we have is a class that will acquire lock only for the first instance creation and the rest of the time it will return the already created instance.

Using the .NET CLR Capabilities for Thread Safety

When we are using C#, we can utilize the CLR behaviour to have a thread safe implementation without the complexity of locking. What we could do is include a static constructor in the class that will take care of the instance creation. The static constructor of a class is called when either the first static member of the class is accessed (in our case it will be GetInstancemethod) or the first instance of the class is created (which is not a valid scenario here as constructor is private). Look at the implementation with the following changes.

public sealed class Singleton
{
    // A private constructor to restrict the object creation from outside
    private Singleton()
    {

    }

    // A private static instance of the same class
    private static readonly Singleton instance = null;

    static Singleton()
    {
        // create the instance only if the instance is null
        instance = new Singleton();
    }

    public static Singleton GetInstance()
    {
        // return the already existing instance
        return instance;
    }
}

Here we moved the instantiation in the static constructor which will get called when the GetInstance method will be called. Static constructor will create the instance and that instance will get returned from by the GetInstance method.

The instance field has been marked as read-only so that it can only be instantiated during static initialization. And, now we have a fairly usable singleton class that is thread safe without the performance overhead of locks.

Note: One might argue that in our last version the initialization is not lazy, as if this class has any other static member then the instance will get created even if it is not requested. There is one more version of singleton possible where this can be circumvented using either nested class or Lazy. But I am not going to discuss them here. In most cases a singleton will not have other static methods. If we find ourselves in a scenario where we have a singleton that also has other static methods, perhaps we are violating the Single Responsibility Principle and should revisit our class design again.

Point of Interest

You will find the code snippets in all the singleton implementations the same as there are not many possible implementations of this pattern with C#. Still, I thought it could really be useful to put an explanation of the pattern in my own words for those who are just starting with this pattern. For more advanced readers, I recommend reading this blog for a much more detailed explanation of this pattern: C# in Depth: Implementing the Singleton Pattern[^].

csharp Singleton pattern

Published at DZone with permission of Rahul Rajat Singh, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • DevOps for Developers: Continuous Integration, GitHub Actions, and Sonar Cloud
  • How To Choose the Right Streaming Database
  • HTTP vs Messaging for Microservices Communications
  • DevOps vs Agile: Which Approach Will Win the Battle for Efficiency?

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: