Is the Order of Static Class Initialization in C# Deterministic

Is the order of static class initialization in C# deterministic?

Straight from ECMA-334:

17.4.5.1: "If a static constructor (§17.11) 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."

And:

17.11: 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 is created.
  • Any of the static members of the class are referenced.

If a class contains the Main method (§10.1) in which execution begins, the static constructor for that class
executes before the Main method is called. If a class contains any static fields with initializers, those
initializers are executed in textual order immediately prior to executing the static constructor (§17.4.5).

So the order is:

  • A.X used, so static A() called.
  • A.X needs to be initialized, but it uses B.X, so static B() called.
  • B.X needs to be initialized, and it is initialized to 7. B.X = 7
  • All static fields of B are initialized, so static B() is called. X is printed ("7"), then it is set to A.X. A has already started being initialized, so we get the value of A.X, which is the default value ("when a class is initialized, all static fields in that class are first initialized to their default value"); B.X = 0, and is printed ("0").
  • Done initializing B, and the value of A.X is set to B.X+1. A.X = 1.
  • All static fields of A are initialized, so static A() is called. A.X is printed ("1").
  • Back in Main, the values of A.X and B.X are printed ("1", "0").

It actually comments upon this in the standard:

17.4.5: It is possible for static fields with variable initializers to be observed in their default value state. However, this is strongly discouraged as a matter of style.

Initialization Order of Static Fields in Static Class

Yes, they will, please see clause 15.5.6.2 of the C# specification:

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.

That being said I think it would be better to do the initialization inside a static type initializer (static constructor).

What's the order of initialization?

If you need deterministic initialization, use a static constructor:

public static List<int> a;
public static List<int> b;

private static Test()
{
a = new List<int>{1,2,3};
b = new List<int>(a);
}

The C#/CLR specification ensures the order in which field initializers are executed, but as you've noticed, if you mess up the ordering of your fields in the class, things break down at runtime. That's a bad idea regardless of the contractual behavior, given how easy it is to switch the order of fields in a class.

So my advice is: if the field initializers don't depend on other fields, keep them. If they do, put the initialization in a constructor, where the ordering is very explicit.

The relevant quote from specification:

If a class contains any static fields with initializers, those initializers are executed in textual order immediately prior to executing the static constructor (§17.4.5).

So you can rely on the textual order contractually, but I'd still recommend against it. It's way too easy to break, and people usually don't consider the order of members in the code file of a class important. It would be fine if you got a compilation error, but you don't - if you're lucky, you get a runtime error. If you're not, you're going to be scratching your head with "impossible" situations that had nothing to do with your changes (right?).

Static initializers vs static constructors, execution orders, release mode behaving oddly

There is a big difference between initializers on a class with a static constructor and without. On classes without a static constructor they can run at any time prior to the first access, much earlier if the runtime so decides. With a static constructor they can only run immediately prior to the first access.

DAL has a static constructor so it's guaranteed to initialize on first access and no earlier.

AppUtil has no static constructor, so it can run as early as it likes, in particular it can run before you initialized DAL.

Your immediate problem should disappear if you add a static constructor to AppUtil even if it's empty.

You should read C# and beforefieldinit by Jon Skeet, where he explains this difference in detail.

To quote the specification:

If a static constructor (§10.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.

The static constructor for a closed class type executes at most once in a given application domain. 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 this kind of initialization pattern is a bad idea on many levels. These initializers are hard to debug, can change their order on a whim.

You should not use static fields for this kind of state in the first place. Create a single instance of these classes during your initialization code instead of using a classic singleton which uses state from outside its own class to initialize. Or even better, use proper Dependency Injection. These kind of services is the place where DI and IoC shine.

Static Field Initializers

Static initialization of fields happens in non-deterministic order, try making the constructors of A and B static, and initialize the variables inside. That ensure it is initialized the first time your class is used and in the order you specified.

Order of initialization of static members in yield return statements

As per the question comment, static initialization is not always deterministic. However, you can make it deterministic using static constructors:

class C1 : B
{
static C1(){}
public static readonly C1 Default = new C1();
}

class C2 : B
{
static C2(){}
public static readonly C2 Default = new C2();
}

That forces each of C1 and C2 to be initialized exactly at the point of first reference - neither earlier than that nor later than that. (Where "at the point of first reference" is defined to be construction of an instance or access to a static member.)

Without a static constructor, type initialization can be eager (i.e. occurs before you first use a type) or surprisingly late. You can create instances, call static and instance methods on a type and still not run the static field initializers - it's only when you refer to a static field that the static field initializers must have been run.

How to initialize a C# static class before it is actually needed?

I would probably just go for the Initialize method - and it can do something useful:

  • It can log that you're explicitly trying to initialize the class, with a stack trace
  • It might throw an exception if the class is already initialized via another Initialize call
  • You could possibly (with a bit of effort and reorganization) sort things so that any exceptions caused during initialization were propagated without the TypeInitializationException which you'd normally get.

Declaration order of types or members in c#

When you write this:

class Program
{

static readonly int A = Method();
static readonly int B = 42;
static int Method() => B;

static void Main()
{
Console.WriteLine(A); // 0
}
}

The compiler will generate a static constructor for you, which assigns the initial values to your various fields. The order of these assignments matches the order that the fields are declared in:

class Program
{

static readonly int A;
static readonly int B;

static Program()
{
A = Method();
B = 42;
}

static int Method() => B;

static void Main()
{
Console.WriteLine(A); // 0
}
}

When the static constructor runs, it's fairly clear that Method() is executed, and A assigned to, before B is assigned to. Fields have an initial value of 0, before anything is assigned to them. So Method() will return 0.

Follow the same logic for your second scenario, and you'll see how it's different.



Related Topics



Leave a reply



Submit