Initialization Order of Static Fields in Static Class

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).

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.

What is the static variable initialization order across classes in C#?

It's fine for one type to depend on another type being initialized, so long as you don't end up in a cycle.

Basically this is fine:

public class Child
{
static Child() {} // Added static constructor for extra predictability
public static readonly int X = 10;
}

public class Parent
{
static Parent() {} // Added static constructor for extra predictability
public static readonly int Y = Child.X;
}

The result is well-defined. Child's static variable initializers are executed prior to the first access to any static field in the class, as per section 10.5.5.1 of the spec.

This isn't though:

public class Child
{
public static readonly int Nasty = Parent.Y;
public static readonly int X = 10;
}

public class Parent
{
public static readonly int Y = Child.X;
}

In this latter case, you either end up with Child.Nasty=0, Parent.Y=10, Child.X=10 or Child.Nasty=0, Parent.Y=0, Child.X=10 depending on which class is accessed first.

Accessing Parent.Y first will start initializing Parent first, which triggers the initialization of Child. The initialization of Child will realise that Parent needs to be initialized, but the CLR knows that it's already being initialized, so carries on regardless, leading to the first set of numbers - because Child.X ends up being initialized before its value is used for Parent.Y.

Accessing Child.Nasty will start initializing Child first, which will then start to initialize Parent. The initialization of Parent will realise that Child needs to be initialized, but the CLR knows that it's already being initialized, so carries on regardless, leading to the second set of numbers.

Don't do this.


EDIT: Okay, more detailed explanation, as promised.

When is a type initialized?

If a type has a static constructor, it will only be initialized
when it's first used (either when a static member is referenced, or
when an instance is created). If it doesn't have a static
constructor, it can be initialized earlier. In theory, it could also
be initialized later; you could theoretically call a constructor or
a static method without the static variables being initialized - but
it must be initialized before static variables are referenced.

What happens during initialization?

First, all static variables receive their default values (0, null
etc).

Then the static variables of the type are initialized in textual
order. If the initializer expression for a static variable requires
another type to be initialized, then that other type will be
completely initialized before the variable's value is assigned -
unless that second type is already being initialized (due to a
cyclic dependency). Essentially, a type is either:

  • Already initialized
  • Being initialized at the moment
  • Not initialized

Initialization is only triggered if the type is not initialized.
This means that when there are cyclic dependencies, it is possible
to observe a static variable's value before its initial value has
been assigned
. That's what my Child/Parent example shows.

After all the static variable initializers have executed, the static
constructor executes.

See section 10.12 of the C# spec for more details on all of this.


By popular demand, here was my original answer when I thought the question was about the initialization order of static variables within a class:

Static variables are initialized in textual order, as per section 10.5.5.1 of the C# 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.

Note that partial types make this trickier as there's no one canonical "textual order" of the class.

Static member initialization order within a single C# class

In short, don't do this.

Standard ECMA-334 C# Language Specification

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

The fix is to :

  • Put them in the order and use Static Constructor,
  • or just Initialise them in a Static Constructor in turn giving you the ability to control the order of initialisation (given the above information).

Personally i suggest to Initialise them in a Static Constructor, it seems to make it more concrete and understandable, and less likely to be bumped in refactoring

Static field initialization sequence in a class

The constant static variables are initialized before any non-static variables are initialized. The JLS, Section 12.4.2, states the initialization procedure for a class:


  1. Otherwise, record the fact that initialization of the Class object for C is in progress by the current thread, and release LC.
    Then, initialize the static fields of C which are constant variables (§4.12.4, §8.3.2, §9.3.1).

(other steps here)


  1. Next, execute either the class variable initializers and static initializers of the class, or the field initializers of the interface, in textual order, as though they were a single block.

So, INSTANCE is listed textually first, before list, map, and name. Why aren't all 3 still null? This is because name is initialized by a constant expression; it is a constant variable. It is initialized first, before INSTANCE, because it it a constant variable.

Note that you can move the line initializing INSTANCE after list and map, causing list and map to be initialized before INSTANCE.

Initialization order of static readonly field

It is in the order that they appear in. See here.

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.

Also, when you have a static constructor:

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. Otherwise, the static field
initializers are executed at an implementation-dependent time prior to
the first use of a static field of that class.

Static field initialization order with partial classes

When the fields are present in the same file, the textual order defines the execution of their initialization:

10.5.5.1 Variable initializers - 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. 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.

However, in the case of fields declared in different files of partial classes, the order is undefined:

10.2.6 Partial types - Members

The ordering of members within a type is rarely significant to C# code, but may be significant when interfacing with other languages and environments. In these cases, the ordering of members within a type declared in multiple parts is undefined.

From the C# language specification.

Order of initialization of static variable in Java

It depends on when each class is first used.

From section 12.4.1 of the Java Language Specification:

A class or interface type T will be initialized immediately before the first occurrence of any one of the following:

  • T is a class and an instance of T is created.

  • T is a class and a static method declared by T is invoked.

  • A static field declared by T is assigned.

  • A static field declared by T is used and the field is not a constant variable (§4.12.4).

  • T is a top level class (§7.6), and an assert statement (§14.10) lexically nested within T (§8.1.3) is executed.

A reference to a static field (§8.3.1.1) causes initialization of only the class or interface that actually declares it, even though it might be referred to through the name of a subclass, a subinterface, or a class that implements an interface.

Section 12.4.2 of the JLS specifies the initialization procedure in detail.

To be honest, if your code requires one to be initialized before the other, despite having no obvious dependency, then you've got problems anyway.

When are static variables initialized?

From See Java Static Variable Methods:

  • It is a variable which belongs to the class and not to object(instance)
  • Static variables are initialized only once , at the start of the execution. These variables will be initialized first, before the initialization of any instance variables
  • A single copy to be shared by all instances of the class
  • A static variable can be accessed directly by the class name and doesn’t need any object.

Instance and class (static) variables are automatically initialized to standard default values if you fail to purposely initialize them. Although local variables are not automatically initialized, you cannot compile a program that fails to either initialize a local variable or assign a value to that local variable before it is used.

What the compiler actually does is to internally produce a single class initialization routine that combines all the static variable initializers and all of the static initializer blocks of code, in the order that they appear in the class declaration. This single initialization procedure is run automatically, one time only, when the class is first loaded.

In case of inner classes, they can not have static fields

An inner class is a nested class that is not explicitly or implicitly
declared static.

...

Inner classes may not declare static initializers (§8.7) or member interfaces...

Inner classes may not declare static members, unless they are constant variables...

See JLS 8.1.3 Inner Classes and Enclosing Instances

final fields in Java can be initialized separately from their declaration place this is however can not be applicable to static final fields. See the example below.

final class Demo
{
private final int x;
private static final int z; //must be initialized here.

static
{
z = 10; //It can be initialized here.
}

public Demo(int x)
{
this.x=x; //This is possible.
//z=15; compiler-error - can not assign a value to a final variable z
}
}

This is because there is just one copy of the static variables associated with the type, rather than one associated with each instance of the type as with instance variables and if we try to initialize z of type static final within the constructor, it will attempt to reinitialize the static final type field z because the constructor is run on each instantiation of the class that must not occur to static final fields.



Related Topics



Leave a reply



Submit