Debugger Doesn't Trigger Static Type Initialization

September 1st 2014 Debugging Visual Studio C#

Let's take a closer look at the following static class:

public static readonly string Field = "Static value";

static StaticClass()
{
  Debug.WriteLine("Static constructor called.");
}

Up until today I was convinced, that given such a class the following couldn't happen:

StaticClass.Field = null

Obviously I was wrong: the static readonly field with an initializer is uninitialized. Of course this required closer examination.

We'll start with the language specification. This is being said about static field initialization in section 10.5.5.1:

The static field variable initializers of a class correspond to a sequence of assignments that are executed in the textual order in which they appear in the class declaration. If a static constructor exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor. Otherwise, the static field initializers are executed at an implementation-dependent time prior to the first use of a static field of that class.

The above class has a static constructor, therefore the following text about static constructors is also relevant (section 10.12):

The execution of a static constructor is triggered by the first of the following events to occur within an application domain:

  • An instance of the class type is created.
  • Any of the static members of the class type are referenced.

Still, no matter what you do, the field initializer should execute before it is accessed for the first time, hence it should never have null value. The above image proves this wrong. We need some more code to get to the bottom of this:

static void Main(string[] args)
{
  Debug.WriteLine("Field value: " + StaticClass.Field);
}

Now let's put a breakpoint before the only line of code is executed and after it. Once the first breakpoint is hit, we can take a look at StaticClass from Immediate Window:

StaticClass
ConsoleApplication2.StaticClass
    base: object
    Field: null

Field is not initialized yet. This doesn't affect the code execution, though. As soon as we run the program to the second breakpoint, we get the following in the output window:

Static constructor called.
Field value: Static value

Repeating the same call in Immediate Window now also gives the expected result:

StaticClass
ConsoleApplication2.StaticClass
    base: object
    Field: "Static value"

As it seems, looking up the field value in debugger doesn't have any side effects - no code gets executed, unlike when accessing properties. But that's already a subject for another post about bad software development practices.

Copyright
Creative Commons License