Differences: Static Class vs. Singleton Patterns

When developing apps with C# in the .NET framework, you have a choice between two single, shared class instances. Whether you decide to use a static keyword or a singleton design pattern depends on several factors, which are outlined in the article below.

Key Differences Between Static Classes and Singleton Patterns

Put simply, a singleton is a pattern while a static class is a keyword. This means you can create one, persistent instance across an application’s entire lifespan with a singleton. The nifty thing about singletons is that a single instance can be used as a parameter for other methods. On the other hand, static classes only permit static methods and can’t be passed as parameters.

Other key differences include:

  • Singletons can inherit from other classes, implement interfaces and permit inheritance, making them more flexible than static classes.

  • You can implement singletons asynchronously or lazily, and the .NET framework CLR can automatically load it.

  • Singletons follow Object-Oriented Principles, letting you handle them polymorphically without forcing users to assume there’s only a single instance.

  • Singletons can dispose but static classes can’t.

  • Static classes are stored in the stack while singletons are stored on the heap.

  • Singletons can clone while static classes can’t.

  • Singletons can have a private constructor.

The Singleton Pattern

Most developers agree the singleton design pattern is the ideal solution. They let you design classes that require a single instance, such as manager classes, for use in caching, thread pools, and logging. They’re also great for managing shared resources such as printer spooling, where you need to avoid conflicting requests for a single resource.

Below is an implementation of a singleton that I’ve used before. As you know, a singleton is a highly-efficient, graceful single-instance object. One of its main features is that it has a static property that you must access to get the object reference.

/// <summary>/// Sample singleton object./// </summary>public sealed class SiteStructure{    /// <summary>    /// Possible an expensive resource we need to only store in one place.    /// </summary>    object[] _data = new object[10];    /// <summary>    /// Allocate ourselves. We have a private constructor, so no one else can.    /// </summary>    static readonly SiteStructure _instance = new SiteStructure();    /// <summary>    /// Access SiteStructure.Instance to get the singleton object.    /// Then call methods on that instance.    /// </summary>    public static SiteStructure Instance    {        get { return _instance; }    }    /// <summary>    /// This is a private constructor, meaning no outsides have access.    /// </summary>    private SiteStructure()    {        // Initialize members, etc. here.    }}

What Is a Static Class?

A static class is a class that can’t be instantiated but also doesn’t require you to fiddle around creating instances for each new object. They consume fewer resources, and you won’t need to duplicate the same class in memory. This makes it a handy container for sets of methods that exclusively operate on output parameters and don’t have to set or get any internal instance fields. If you only require a utility class with several utility methods, a static class’s simple implementation can improve app performance, making it a better option.

Its major disadvantage in comparison to singleton patterns is that you can’t change how it behaves once the class is decorated with the static keyword. However, the singleton pattern’s prowess doesn’t end there. Let’s take a look at the major differences between the two class instances.

Static Class Example

In the following example, take a look at how I use a static keyword on the class and constructor. Static classes may be less fiddly, but the singleton example has many important advantages, which we’ll take a look at after this code block.

/// <summary>/// Static class example. Pay heed to the static keywords./// </summary>static public class SiteStatic{    /// <summary>    /// The data must be a static member in this example.    /// </summary>    static object[] _data = new object[10];    /// <summary>    /// C# doesn't define when this constructor is run, but it will     /// be run right before it is used most likely.    /// </summary>    static SiteStatic()    {        // Initialize all of our static members.    }}

You can use static classes to store single-instance, global data. The class can be initialized at any time, but in my experience, it’s initialized lazily — in other words, at the last possible moment. As such, you might lose control over the exact behavior of the class by using a static class.

Singleton Advantages in Action

Singletons preserve the conventional class approach and don’t require that you use the static keyword everywhere. They may be more demanding to implement at first, but they greatly simplify your program’s architecture. Unlike static classes, it’s possible to use singletons as parameters or objects.

// We want to call a function with this structure as an object.// Get a reference from the Instance property on the singleton.{    SiteStructure site = SiteStructure.Instance;    OtherFunction(site); // Use singleton as parameter.}

Interface Inheritance

In C#, an interface is a contract, and objects that have an interface must meet every requirement of that interface. Usually, the requirements are a subset of the object in question. Here’s how we can use a singleton with an interfacewhich is called ISiteInterface in the example.

/// <summary>/// Stores signatures of various important methods related to the site./// </summary>public interface ISiteInterface{};/// <summary>/// Skeleton of the singleton that inherits the interface./// </summary>class SiteStructure : ISiteInterface{    // Implements all ISiteInterface methods.    // [omitted]}/// <summary>/// Here is an example class where we use a singleton with the interface./// </summary>class TestClass{    /// <summary>    /// Sample.    /// </summary>    public TestClass()    {        // Send singleton object to any function that can take its interface.        SiteStructure site = SiteStructure.Instance;        CustomMethod((ISiteInterface)site);    }    /// <summary>    /// Receives a singleton that adheres to the ISiteInterface interface.    /// </summary>    private void CustomMethod(ISiteInterface interfaceObject)    {        // Use the singleton by its interface.    }}

Now we can reuse our singleton for any of the implementations of interface-conforming objects. There may be 1, 2, or 10. We don’t need to rewrite anything over and over again. We store state more conventionally, use objects by their interfaces, and can use traditional object-oriented programming best practices. Reusing code can control the object state much more easily. This facilitates greatly improved code-sharing and an infinitely cleaner body of code.

Conclusion

With less code, your programs tend to have fewer bugs and are easier to maintain. Other advantages of singleton patterns over static classes are:

  • Testability: Testing singleton patterns is much easier than static classes

  • Memory management: Using a singleton class lets you take advantage of garbage collection for managed objects

  • Dependency injection: You can’t use constructor injection with static classes, but you can with singletons

  • Extensibility: You can have extension methods with a singleton class but not a static class

If you want to learn more about singleton vs. static, “C# Design Patterns” by Judith Bishop is a worthwhile reading.

.

Leave a Comment