Which static class initializes first?
Which static class initializes first if we have one more static classes in our project?
For example: Below code gives null exception.
class Program
{
static void Main(string[] args)
{
First.Write();
Second.Write();
}
}
static class First
{
public static int[] firstArray = new int[20];
public static int[] secondArray = Second.secondArray;
public static void Write()
{
Console.WriteLine(firstArray.ToString());
Console.WriteLine(secondArray.ToString());
}
}
static class Second
{
public static int[] firstArray = First.firstArray;
public 开发者_高级运维static int[] secondArray = new int[30];
public static void Write()
{
Console.WriteLine(firstArray.ToString());
Console.WriteLine(secondArray.ToString());
}
}
If you pay attention, you will see that if First
class will initialize itself so secondArray
field of Second
would be null. But if Second
class would initialize first so Second
class firstArray
would be null. I am trying to tell that which initialize first makes different results.
I think that it is abstract question about my project. I encounter it while trying to understand why I am getting unexpected results.
First
will begin to initialize, assign firstArray
, then notice that it requires Second
to be initialized in order to get the initial value of secondArray
.
Second
will start initializing, and then notice that it requires First to be initialized. However, the CLR will then notice that First is already initializing in the current thread, so it won't block. Second
's initialization will complete, and then First's initialization will complete.
Fortunately, the field that Second
needs has already been assigned, so the "right thing" happens.
That's all very well if First
actually starts initializing first. However, as neither of the classes has a static constructor, it's possible that Second
will start to initialize first... it would then start to initialize First
, which would spot that Second
is already initializing and take Second.secondArray
's current value (null) for First.secondArray
. This would be a Bad Thing. Note that the initialization timing for types without static constructors has changed in .NET 4 - not in a spec-breaking way, but possibly in an existing-code-breaking way.
If both First
and Second
had static constructors, then First
would be initialized first, as that's the first class that Main
touches.
Moral of the answer: don't do this. Type initializers which refer to each other are very error prone. For another example, see Eric Lippert and Neal Gafter's NDC 2010 talk, "C# Puzzlers" which can be viewed on the NDC video page.
I don't believe there is any guarantee as to which static type is initialised first. To ensure fields are initialised properly this way, you'd need to add a static constructor, e.g.:
static class Second
{
public static int[] firstArray = First.firstArray;
public static int[] secondArray = new int[30];
static Second() { }
public static void Write()
{
Console.WriteLine(firstArray.ToString());
Console.WriteLine(secondArray.ToString());
}
}
Now, when you run the same thing again, it works...
精彩评论