How do static constructors for generic types work?
public abstract class EventSystemBase<T, K> : IAutoEvent
w开发者_如何学JAVAhere T : Event
where K : IAutoEvent, new()
{
public static T Instance { get { return EventSystem.Events.OfType<T>().FirstOrDefault(); } }
public static IAutoEvent AutoEventInstance { get { return new K(); } }
static EventSystemBase()
{
EventBot.Register(new EventBotEntry(Instance.Name, AutoEventInstance));
}
[...]
}
I don't really understand how this compiles.
- When does the static constructor run?
- Why can I use generic types in static members?
- How is it supposed to know which types to apply?
The static constructor is at the first moment it is needed. The exact timing is a bit tricky because if flags like
beforefieldinit
in the binary; you probably don't need to worry too much about the details except that it's run when the first class member is accessed, before it is needed.Well, why not? :) Every type of the form
EventSystemBase<T, K>
is its own separate class and bears no relation to the other generic instances of the class, so the constructor needs to run for each one. They're all different to the runtime in all* respects.The static constructor runs for a "cooked" type and not the "raw" type (i.e. it runs for the version with the generic types substituted), so there's no real problem here.
*Actually, the runtime avoids creating duplicate instances of reference type generics. But that doesn't matter here, to the programmer or to the program.
The static constructor isn't for the open generic type. It will only run when you have specified the type paramaters, e.g., EventSystemBase<MyEvent, MyAutoEvent>
, which is actually a different class than e.g., EventSystemBase<AnotherEvent, MyAutoEvent>
with its own static constructor. In each case, the static constructor runs before the first instance of that separate class is created or any of its static members are referenced.
If it applies the same from my c++ knowledge back in the day...
Generics are generated at compile time, and they are converted into many seperate and distinct classes. For each of theses classes, the static constructor runs before any code references the static class. The CLR knows which types to reference because each of the classes are unique.
EventSystemBase<string, byte> has absolutely no relationship with EventSystemBase<string, int>. It is as if you have written two entirely separate classes in your source code.
class Program
{
public static void Main()
{
var myInt = new MyGeneric<int>();
myInt.InstanceMethod();
MyGeneric<int>.StaticMethod();
MyGeneric<long>.StaticMethod();
var myLong = new MyGeneric<long>();
myLong.InstanceMethod();
Console.ReadLine();
}
}
public class MyGeneric<T>
{
static MyGeneric()
{
Console.WriteLine("Static constructor: {0}", typeof(T).Name);
}
public static void StaticMethod()
{
Console.WriteLine("Static method: {0}", typeof(T).Name);
}
public void InstanceMethod()
{
Console.WriteLine("Instance method: {0}", typeof(T).Name);
}
}
- The static constructor on the generic is invoked each time you invoke a different < T,K> generic class.
2-3. with 1 it should be clear, it is releated to the T,K generic
精彩评论