Previously on FAIC we saw how easy it was to deadlock a program by trying to do something interesting in a static constructor.

Jargon note: Static constructors are also called “class constructors”. Since the actual method generated has the name .cctor they are often also called “cctors”. Since “static constructor” is the jargon used in the C# specification, that’s what I’ll stick to.

Static constructors and destructors are the two really weird kinds of methods, and you should do as little as possible in them.

Before I expound further on that topic though, a look at how static constructors work is in order. And before I do that, it’s probably a good idea that you get a refresher on how instance constructors work. My article “Why do initializers run in the opposite order of constructors?” provides a detailed look at constructor semantics, so maybe check that out if you have a few minutes. Part one is here and part two is here.

OK, now that you know how instance constructors work, let’s dig into static constructors. The idea is pretty simple: a static constructor is triggered to run immediately before the first static method on its class is called, or immediately before the first instance of its class is created. As we saw previously, the runtime tracks when a static constructor is “in flight” and uses that mechanism to ensure that each static constructor is invoked no more than once.

Now that you know all of that, you can predict the output of this simple program:

using System; class B { static B() { Console.WriteLine("B cctor"); } public B() { Console.WriteLine("B ctor"); } public static void M() { Console.WriteLine("B.M"); } } class D : B { static D() { Console.WriteLine("D cctor"); } public D() { Console.WriteLine("D ctor"); } public static void N() { Console.WriteLine("D.N"); } } class P { static void Main() { System.Console.WriteLine("Main"); new D(); } }

We know that B’s instance constructor must be invoked before D’s instance constructor, and we know that D’s static constructor must be invoked before D’s instance constructor. The only interesting question here is “when will B’s static constructor be invoked?” An instance of D is also an instance of B, so B’s static constructor has to be invoked at some point.

As you know from reading my article on instance constructors, what actually happens is that the compiler generates D’s instance constructor so that the first thing it does is call B’s instance constructor; that’s how we get the appearance that B’s instance constructor runs first. Thus, the actual order of events here can be best conceptualized like this:

Main starts. It prints out its message and then tries to invoke D’s instance constructor on a new instance of D.

The runtime detects that D’s instance constructor is about to be invoked, so it invokes D’s static constructor.

D’s instance constructor invokes B’s instance constructor. The runtime detects that, so it invokes B’s static constructor.

B’s instance constructor runs and returns control to D’s instance constructor, which finishes normally.

Pretty straightforward. Let’s mix it up a little.

Next time on FAIC: A brief digression for fun on a Friday. Then next week we’ll resume this series and take a look at a few less straightforward cases.