Singletons in C#

Tamás Polgár
Developer rants
Published in
2 min readMar 15, 2024

Singletons are objects that exist in only one instance, and every attempt at instantiating a new one will return the original one. They provide a convenient and straightforward way to provide a stateful object all across your namespace (and beyond, if needed) with the state remaining identical.

Not to be confused with a single ton

Some weeks ago I already posted about singletons, but people smarter than me (they’re rare) told me that I was introducing an outdated method, which isn’t thread safe. They were right, and it was one of the rare cases when I removed an article. I remained in debt ever since, so here we go.

This is how you create a C# singleton in a thread safe way:

namespace Whatever
{
internal sealed class MySingleton
{
private static readonly Lazy<MySingleton> lazyInstance = new Lazy<MySingleton>(() => new MySingleton());

public static MySingleton Instance
{
get
{
return lazyInstance.Value;
}
}

private MySingleton()
{
}

public void HelloWorld()
{
Console.WriteLine("Go away, world!");
}
}
}

There are several other ways in fact, it’s just the solution I settled with. Let’s break it down.

First, we declare a class named MySingleton. It will be internal because why not, and sealed because no touchy.

Then we declare a private readonly variable named lazyInstance of type Lazy<MySingleton>. The Lazy type is very a simple animal. Microsoft’s online .NET documentation explains it in a single sentence:

“Provides support for lazy initialization.”

What is lazy though? It means the variable will only spawn to existence when it’s needed. This is particularly useful for large objects, which consume a considerable amount of memory. A class is usually a large object.

In the next line, we declare a static getter named Instance, of type MySingleton. This getter will return the value of lazyInstance. In other words, if the getter is called by any other object, it will create the lazy instance, and return it. Or, if the lazy instance was already called before, by anyone, it returns the instance created at the first call. It’s a generally accepted naming convention to call this getter Instance.

Then finally we have another private function, which is a bog standard constructor. In this example, it is empty. You can add your own methods and properties after it. In this example, I added a HelloWorld() method as demonstration.

How to use a singleton? You don’t instantiate with the new keyword, but call the Instance getter:

MySingleton.Instance.HelloWorld();

One important thing: methods of a singleton shouldn’t be declared as static. It’s not against the law, but you can’t call a static method by referring to Instance. If you still insist to have static methods, just call them as you would with a regular class:

MySingleton.MyStaticMethod();

However, if you only have static methods, you may not need a singleton at all. It’s only useful if your class has state.

--

--