Reputation: 12583
Consider this example code:
public class A<T>
{
public static T TheT { get; set; }
}
public class B : A<string>
{
static B() {
TheT = "Test";
}
}
public class Program {
public static void Main(String[] args) {
Console.WriteLine(B.TheT);
}
}
Here B.TheT
is null. However, changing the Main
method like this:
public static void Main() {
new B();
Console.WriteLine(B.TheT);
}
B.TheT
is "Test", as expected. I can understand that this forces the static constructor to run, but why does this not happen for the first case?
I tried reading the spec, and this caught my attention (§10.12):
[...] The execution of a static constructor is triggered by the first of the following events to occur within an application domain:
• [...]
• Any of the static members of the class type are referenced.
My interpretation of this is that since TheT
is not a member of B
, the static constructor of B
is not forced to be run. Is this correct?
If that is correct, how would I best let B
specify how to initialize TheT
?
Upvotes: 6
Views: 508
Reputation: 1500695
A.TheT is "Test", as expected. I can understand that this forces the static constructor to run, but why does this not happen for the first case?
Basically, you haven't really referenced B
. If you look in the IL, I think you'll find that your code was actually equivalent to:
public static void Main(String[] args) {
Console.WriteLine(A<string>.TheT);
}
The compiler worked out that that's really the member you meant, even though you wrote B.TheT
.
If that is correct, how would I best let A specify how to initialize TheT?
I would try to avoid doing this to start with, to be honest... but you could always just add a static method to B
:
public static void Initialize() {
// Type initializer will be executed now.
}
Upvotes: 5
Reputation: 62256
In second case called static contructor and it will call the actual types' static contructor, and not that one of derived one. So in your case it calls the static ctor of the A<T> =>A<string>
and not of A
.
To prove this behaviour just do the following:
public class Base {
static Base() {
"Base static".Dump();
}
}
public class Derived : Base {
static Derived() {
"Derived static".Dump();
}
public static string temp = "Hello";
}
and call
Derived.temp.Dump();
You will get:
Derived static
Hello
This is what you actually do in your code, you acess derived type A<string>
and it's default static ctor is called.
Upvotes: 0
Reputation: 16708
Static constructor is called before the first access or at the latest when the first access is made. I.e you know it has been called when first access is made but not how long before. However, if no access is made it won't be called. So you cannot control when only if it s called.
As per MSDN reference
A static constructor is used to initialize any static data, or to perform a particular action that needs performed once only. It is called automatically before the first instance is created or any static members are referenced.
Upvotes: 0