Reputation: 4506
I have a design that relies heavily on static initialization. I've noticed that after a series of OS updates, my design appears to be failing on some older versions of the .NET Framework (v<3.5), and only under Release configuration.
I think I've been able to narrow the issue down to a block of code similar in design to this:
public abstract class Foo { public static object A; }
public class Bar : Foo {
public static object B = InitB();
private static object InitB(){ return A }; }
public static void Main()
{
Foo.A = new object();
Bar bar = new Bar();
Console.Write((bar.B==null).ToString());
}
On .NET 2.0, under Release build, on my system, it appears my code is printing true
. Whereas on .NET 4.5, it's printing false
. Is the behavior of the code above implementation specific?
Upvotes: 2
Views: 81
Reputation: 82096
Is the behaviour of the above code implementation specific
For the example above, the docs would suggest that is the case
If a static constructor 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.
For consistency across .NET versions, and to force initialization order, you should add a static constructor to both classes.
Upvotes: 0
Reputation:
Your code relies on Bar
's static constructor being called after the assignment to Foo.A
. The language spec does not guarantee this. It only guarantees it if you actually write a static constructor, not if the compiler implicitly generates one: in that case, it may be called earlier than you expect.
To make sure your code behaves the same way in all valid implementations of .NET Framework, add a static constructor. You don't need to re-factor your initialisers, they can remain where they are.
public class Bar : Foo {
static Bar() { } // <-- add this
public static object B = InitB();
private static object InitB() { return A };
}
Alternatively, re-work your code in such a way that it still works even if the static constructor is called early.
Upvotes: 1