问题
According to the docs:
A static constructor is used to initialize any static data, or to perform a particular action that needs to be performed once only. It is called automatically before the first instance is created or any static members are referenced.
But i saw in stackoverflow post, the following quote from the C# specification:
If a static constructor (§10.12) exists in the class, execution of the static field initializers occurs immediately prior to executing that static constructor.
It's contradicting, i don't understand what come first, the static constructor or the static member initialization.
回答1:
Consider this class:
public static class TestStatic
{
public static int SomeValue = GetValue();
static TestStatic()
{
Console.WriteLine("Constructor");
}
}
And this supporting method:
public static int GetValue()
{
Console.WriteLine("GetValue");
return 5;
}
If you run this code:
Console.WriteLine(TestStatic.SomeValue);
The output you will get is:
GetValue
Constructor
5
So you can see that both of the statements you posted are correct. The constructor is called before the static member (SomeValue
) is referenced and the static field initialiser is called before the constructor.
回答2:
Both of the statements you have mentioned are true and are in sync with each other. I am not sure why you think they are contradicting.
The order of execution is as follows:
- Static fields with initializers.
- Static Constructor.
The above is as per your second statement. The first statement just mentions when these actions are performed i.e. before:
- The first instance of the class is created.
- Any static members are referenced.
In fact, the above conditions can be taken as guaranteed for static constructors that the static field initializers will be executed and static constructor will be called before any of the two happens (statement 1).
The C# specification clearly mentions:
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. If a class contains the Main method (Section 3.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.
Just to add on, since you have highlighted -
before the first instance is created or any static members are referenced.
This just means that it is possible to refer to a static member of a class even before creating an instance of that class. So, even in that case, the static constructor will be called before accessing the static member.
If you see DavidG's code in his answer, even though the class is not being instantiated, but one of the static members is being referenced, still the static field initialization takes place before that which is followed by static constructor execution.
Example:
public static class Test
{
public static int i = 10;
public static int j = new Func<int>(() => {
Console.WriteLine("Static field initializer called."); return 20;
})();
static Test()
{
Console.WriteLine("Static Constructor called.");
}
}
Now if you execute:
Console.WriteLine(Test.i);
You get the following output:
Static field initializer called.
Static Constructor called.
10
回答3:
The reason for such a behavior (and it's by design) is that the initialization of static fields actually happens as part of the static constructor. The compiler prepends the static constructor logic with all the expressions you have for static fields' initializers.
来源:https://stackoverflow.com/questions/42753909/static-constructor-is-called-before-any-static-members-are-referenced