When Is a Static Constructor Called in C#

When is a static constructor called in C#?

When the class is accessed for the first time.

Static Constructors (C# Programming Guide)

A static constructor is used to initialize any static data, or to perform a particular action that needs performed once only. It is called automatically before the first instance is created or any static members are referenced.

Static constructor is called before any static members are referenced

Consider this class:

public static class TestStatic
{
public static int SomeValue = GetValue();

static TestStatic()
{
Console.WriteLine("Constructor");
}

}

And this supporting method:

public static int GetValue()
{
Console.WriteLine("GetValue");
return 5;
}

If you run this code:

Console.WriteLine(TestStatic.SomeValue);

The output you will get is:

GetValue
Constructor
5

So you can see that both of the statements you posted are correct. The constructor is called before the static member (SomeValue) is referenced and the static field initialiser is called before the constructor.

Implicit static constructor called before Main()

This is a quirk of chained static class initialization.

From the ECMA C# Specifications

15.5.6.2 Static field initialization

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 (§15.5.6.1). Within a
partial class, the meaning of "textual order" is specified by
§15.5.6.1. If a static constructor (§15.12) 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.

Take special note of the last part, this is your problem, if you don't have a static constructor you have no control over when the field is initialized. In your test case they are being initialized before you call Enterprise.Initialize

In short, you shouldn't be relying on these rules, it's easy to make mistakes and is likely to cause weird issues.

Static constructor called after instance constructor?

Inline initializers for static fields run before the explicit static constructor.

The compiler transforms your class into something like this:

public class Test {
.cctor { //Class constructor
Test.test = new Test(); //Inline field initializer
Console.WriteLine("static Test()"); //Explicit static ctor
}
.ctor { ... } //Instance constructor
}

Note that this is independent of the declaration order.

To quote the spec:

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 (Section 10.11) exists in
the class, execution of the static
field initializers occurs immediately
prior to executing that static
constructor.

What is the use of static constructors?

No you can't overload it; a static constructor is useful for initializing any static fields associated with a type (or any other per-type operations) - useful in particular for reading required configuration data into readonly fields, etc.

It is run automatically by the runtime the first time it is needed (the exact rules there are complicated (see "beforefieldinit"), and changed subtly between CLR2 and CLR4). Unless you abuse reflection, it is guaranteed to run at most once (even if two threads arrive at the same time).

What's the best way to ensure a base class's static constructor is called?

The rules here are very complex, and between CLR 2.0 and CLR 4.0 they actually changed in subtle and interesting ways, that IMO make most "clever" approaches brittle between CLR versions. An Initialize() method also might not do the job in CLR 4.0 if it doesn't touch the fields.

I would look for an alternative design, or perhaps use regular lazy initialization in your type (i.e. check a bit or a reference (against null) to see if it has been done).

Calling of Static Constructor and Instance Constructor

First off, the behaviour is not contradictory at all; it is all consistent with the rules. You just don't know what the rules are.

You should read all of my two-part series on instance constructors and my four-part series on the semantics of static constructors. They start here:

http://blogs.msdn.com/b/ericlippert/archive/2008/02/15/why-do-initializers-run-in-the-opposite-order-as-constructors-part-one.aspx

and here:

http://ericlippert.com/2013/02/06/static-constructors-part-one/

respectively.

Those should clearly answer your question, but in case it is not 100% clear let me sum up. The relevant rules are:

  • Rule One: A static constructor runs before any static field is accessed, before any static method is executed, and before any instance constructor is executed.
  • Rule Two: A derived-class instance constructor calls the base class instance constructor before it runs the derived class instance constructor body.

So what happens when you execute new Child()?

  • Rule One applies. We are about to call the instance constructor of Child, so we must first call the static constructor of Child. So it runs first.
  • After the static constructor of Child returns, the instance constructor of Child runs. Rule Two applies: the first thing the Child instance constructor does before it runs its body is runs the instance constructor of Parent.
  • Rule One applies again. We are about to call the instance contructor of Parent, so we must first call the static constructor of Parent. So it runs.
  • After the static constructor of Parent returns, the instance constructor of Parent runs. Rule Two applies: it invokes the instance constructor of object, which does nothing interesting, and then runs the body of the instance constructor of Parent.
  • Control returns to the instance constructor of Child, and its body runs.

So there you go; the order is the Child static constructor, then the Parent static constructor, then the Parent body, then the Child body.

Now let's look at your second example. What happens when you say new XyzChild?

  • Rule One applies. We are about to call the instance constructor of XyzChild, so we first call the static constructor of XyzChild. It's body starts executing, and...
  • ...Rule One applies again. We are about to access a static field of XyzParent, so XyzParent's static constructor must execute.
  • XyzParent's static constructor executes. It accesses a field, but the static constructor is already in flight on this thread, so it does not recursively trigger the static constructor again. It prints out that it is in the parent.
  • Control returns to the child's static constructor, which prints out that it is in the child.
  • Now the child's instance constructor can run. Rule Two applies: XyzParent's instance constructor runs first.
  • Rule One applies, but the static constructor for XyzParent has already run, so it is skipped.
  • The body of XyzParent's instance constructor executes and returns control to XyzChild's static constructor.
  • The body of XyzChild's instance constructor runs.

So there you go. There's no inconsistency whatsoever; the two rules are applied correctly.



Related Topics



Leave a reply



Submit