C# Back to Basics: Static Constructors

Wednesday Jan 25th 2017 by Gavin Lanata
Share:

Static constructors are a very basic, yet highly useful, feature of C#. Get the hang of using them here.

Today, let's turn our attention to a very basic, and highly useful feature of C#: Static Constructors. I don't make common use of this feature myself. But, when it is needed, it fits the job very well indeed.

So, what is a static constructor?

To quote the documentation, "A static constructor is used to initialize any static data, or to perform a particular action that needs to be performed once only."

To start with, let's look at some code that satisfies the first part of that quote, and initialize some static data.

public class Clock
{
   static DateTime TIME_STATIC_CONSTRUCTOR_WAS_CALLED;

   static Clock()
   {
      TIME_STATIC_CONSTRUCTOR_WAS_CALLED = DateTime.UtcNow;
   }
}

In the preceding code, we have a static constructor that is used to initialize a static field of type DateTime with the current UTC time. Very simple. However, there are a few things we can note from this code. Firstly, the static constructor does not take any access modifiers. So, for example, if we were to do this…

public static Clock()
{
   TIME_STATIC_CONSTRUCTOR_WAS_CALLED = DateTime.UtcNow;
}

…you would see an error. Furthermore, a static constructor does not accept any parameters, and it cannot be called directly. It is called automatically to initialize the class before the first instance is created or any static members referenced.

My complete code at this point looks like this…

public class Program
{
   public static void Main(string[] args)
   {
      var clock = new Clock();

      Console.WriteLine(clock.Get().Ticks);
   }
}

public class Clock
{
   static DateTime TIME_STATIC_CONSTRUCTOR_WAS_CALLED;

   static Clock()
   {
      TIME_STATIC_CONSTRUCTOR_WAS_CALLED = DateTime.UtcNow;
   }

   public DateTime Get()
   {
      return TIME_STATIC_CONSTRUCTOR_WAS_CALLED;
   }
}

Running this code, which is part of a standard .NET console application, I have an output that looks like Figure 1.

The console application running
Figure 1: The console application running

Now that we have a simple application you may run, let's look at the second part of the quote above, and examine what we mean by 'to perform an action only once.'

As we now know, a static constructor is automatically called once, and called to initialize a class before the first instance of that class is created. Consider the following piece of code.

public static void Main(string[] args)
{
   var clock1 = new Clock();
   Console.WriteLine(clock1.Get().Ticks);

   Thread.Sleep(1000);
   var clock2 = new Clock();
   Console.WriteLine(clock2.Get().Ticks);

   Thread.Sleep(1000);
   var clock3 = new Clock();
   Console.WriteLine(clock3.Get().Ticks);
}

What would you expect the output to the console to be for the other two instances of Clock? The exact DateTime they were initialized? Or the DateTime of the first instance of the class? For the answer, see Figure 2…

The output from the three instances of Clock
Figure 2: The output from the three instances of Clock

Let's compare the behaviour from above, with that of a standard constructor. Let's change the static constructor of our Clock class to something like the following, and re-run the program.

public Clock()
{
   TIME_STATIC_CONSTRUCTOR_WAS_CALLED = DateTime.UtcNow;
}

And the result…

The output showing different results
Figure 3: The output showing different results

The ticks we are looking at now represent the time at which the constructor was called. Each one differs because we are making that call every time the class is initialized.

Conclusion

There isn't a lot to this little feature of C#, but its application can be very powerful to you at the right time. For example, if you're familiar with EntityFramework, you may need to evaluate a connection string at run-time, rather than connected using a constant string. It's also quite possible that once you've evaluated this string, you don't need to do so again for the lifetime of the application.

This is the kind of situation a static constructor can really help, and one I've recently found myself in with a WPF application. I ended up in a situation where the location of a local SQLite database can change, but it never changes once the application is running.

If you have any questions or comments on this article, please find me on Twitter @GLanata.

Share:
Home
Mobile Site | Full Site
Copyright 2017 © QuinStreet Inc. All Rights Reserved