This past week I came across a C# code with a very surprising behavior. This simple program will better explain the observed behavior. What would you expect as output?
class Program { static void Main(string[] args) { A.Initialize(); Console.WriteLine("B.Y:{0} - A.X:{1}", B.Y, A.X); Console.ReadKey(); } } public static class Util { public static int InitMember( string message, int initValue) { Console.WriteLine( message ); return initValue; } } public static class A { public static int X = Util.InitMember( "Init A.X", 5 ); public static void Initialize() { Console.WriteLine( "A.Initialize()" ); X = 10; } } public static class B { public static int Y = Util.InitMember( "Init B.Y", A.X ); }
If you guessed:
“B.Y: 10, A.X: 10”
Keep reading, this post is for you. 🙂
In the machine I ran this experiment I got this output: “B.Y: 5, A.X: 10”. The full output also revealed that class A and B were initialized before any of its members were accessed. How is it possible that A.Initialize() runs after B.Y? Full Output:
“Init B.Y”
“A.Initialize()”
“B.Y:5, A.X:10”
Introducing: beforefieldinit
!
beforefieldinit
is a class attribute that has a very interesting proposition. Its presence can be easily observed by using a simple disassemble tool (ILDASM.exe) as suggested per Scott Allen’s post.
Msdn simply states that this attribute: Specifies that calling static methods of the type does not force the system to initialize the type. It is pretty clear from this statement that this flag intends to improve performance, but c’mon msdn, we need a little more than that. Fortunately, a C# in depth post came in handy. It states that a “The beforefieldinit
flag has a strange effect, in that it can not only mean that a type initializer is invoked earlier than that of an equivalent type without the flag – it could even be invoked later, or not at all. … The runtime could decide to run the type initializer on loading the assembly… Or perhaps it will run it when the static method is first run…Or even wait until the field is first accessed.” . In summary, this flag gives great freedom to CLR to initialize a static class. In my test application this is exactly what I observed, static class A and static class B were initialized before my first line of code.
This non-deterministic can be avoided by adding an empty static constructor to class A and B at the cost of performance. This constructor will force CLR to remove the beforefieldinit
flag. According to the C# specification:
The static constructor for a class 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 is created.
- Any of the static members of the class are referenced.
Here is the code with a static constructor:
class Program { static void Main(string[] args) { A.Initialize(); Console.WriteLine("B.Y:{0} - A.X:{1}", B.Y, A.X); Console.ReadKey(); } } public static class Util { public static int InitMember( string message, int initValue) { Console.WriteLine( message ); return initValue; } } public static class A { public static int X = Util.InitMember( "Init A.X", 5 ); public static void Initialize() { Console.WriteLine( "A.Initialize()"; ); X = 10; } static A(){} } public static class B { public static int Y = Util.InitMember( "Init B.Y", A.X ); static B(){} }
Once again ILDASM can help us observe the absence of the beforefieldinit
attribute:
And finally, the “expected” output:
“A.Initialize()”
“Init B.Y”
“B.Y:10, A.X:10”