Should static field initialization be completed before constructor is called?
The following program provides output that seems incorrect to me.
new A() _A == null static A() new A() _A == A
The code:
public class A { public static string _A = (new A()).I(); public A() { Console.WriteLine("new A()"); if (_A == null) Console.WriteLine("_A == null"); else Console.WriteLine("_A == " + _A); } static A() { Console.WriteLine("static A()"); } public string I() { return "A"; } } class Program { static void Main(string[] args) { var a = new A(); } }
The only way to initialize static final variables other than the declaration statement is Static block. A static block is a block of code with a static keyword. In general, these are used to initialize the static members. JVM executes static blocks before the main method at the time of class loading.
A static field is in programming languages is the declaration for a variable that will be held in common by all instances of a class. The static modifier determines the class variable as one that will be applied universally to all instances of a particular class.
You can define a static field using the static keyword. If you declare a static variable in a class, if you haven't initialized it, just like with instance variables compiler initializes these with default values in the default constructor. Yes, you can also initialize these values using the constructor.
You initialize a static object with a constant expression, or an expression that reduces to the address of a previously declared extern or static object, possibly modified by a constant expression.
This is correct.
Your static initializers, then the static constructor is run before your standard constructor, but when it runs, it's using new A(), so passing through your non-static constructor path. This causes the messages you see.
Here is the full path of execution:
When you first call var a = new A();
in your program, this is the first time A is accessed.
This will fire off the static initialization of A._A
At this point, A._A constructs with _A = (new A()).I();
This hits
Console.WriteLine("new A()"); if (_A == null) Console.WriteLine("_A == null");
since at this point, _A hasn't been set with the returned, constructed type (yet).
Next, the static constructor A { static A(); }
is run. This prints the "static A()" message.
Finally, your original statement (var a = new A();
) is executed, but at this point, the statics are constructed, so you get the final print.
One extra side note - the C# specification (I'm looking at 4.0, but it's there in 3.0 too) says in 10.5.5.1 Static Field Initialization:
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.
You have a static constructor, so the "Otherwise" clause does not apply. But I think it's relevant information to your question to know that if you don't have a static constructor, the static field initializers can be executed 'at an implementation-dependent time'. This could matter if your static field initializer is doing some type of data initialization or object creation which you rely on without accessing the static field itself.
It is esoteric, I guess, but I saw it happen today as the 'implementation-dependent time' appears to have changed between C# 3.0 and 4.0 - at least for the situation I was looking at. The easy solution of course is simple - just add a static constructor...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With