C#Generic Static Constructor

Sea*_*ard 52 c# generics

是否会为传递给泛型参数的每个类型运行泛型类上的静态构造函数,例如:

 class SomeGenericClass<T>
 {
      static List<T> _someList;
      static SomeGenericClass()
      {
          _someList = new List<T>();
      }
 }
Run Code Online (Sandbox Code Playgroud)

使用这种方法是否有任何缺点?

Mar*_*ers 62

是的,对于每个封闭的类类型(指定类型参数时创建的类型),将为静态构造函数调用一次.请参阅C#3规范,§10.12静态构造函数.

封闭类类型的静态构造函数在给定的应用程序域中最多执行一次.

并且:

因为静态构造函数对于每个关闭的构造类类型只执行一次,所以对于无法在编译时通过约束(第10.1.5节)检查的类型参数强制执行运行时检查是一个方便的地方.例如,以下类型使用静态构造函数来强制类型参数是枚举:

class Gen<T> where T: struct
{
    static Gen() {
        if (!typeof(T).IsEnum) {
            throw new ArgumentException("T must be an enum");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

阅读§4.4.2开放和封闭类型也是相关的:

在运行时,泛型类型声明中的所有代码都是在通过将类型参数应用于泛型声明而创建的闭合构造类型的上下文中执行的.泛型类型中的每个类型参数都绑定到特定的运行时类型.所有语句和表达式的运行时处理始终以闭合类型进行,而打开类型仅在编译时处理期间发生.

每个闭合构造类型都有自己的一组静态变量,这些变量不与任何其他闭合构造类型共享.

您可以自己运行的这个程序演示了静态构造函数被调用三次,而不只是一次:

public class Program
{
    class SomeGenericClass<T>
    {
        static SomeGenericClass()
        {
            Console.WriteLine(typeof(T));
        }
    }

    class Baz { }

    static void Main(string[] args)
    {
        SomeGenericClass<int> foo = new SomeGenericClass<int>();
        SomeGenericClass<string> bar = new SomeGenericClass<string>();
        SomeGenericClass<Baz> baz = new SomeGenericClass<Baz>();
    }
}
Run Code Online (Sandbox Code Playgroud)

输出:

System.Int32
System.String
Program+Baz

  • @Jouke van der Maas谈到静态课程?问题是关于泛型类的静态构造函数,而不是静态类...... (6认同)