写在前面
今天在创建WPF自定义控件时,在模板代码中看到了静态构造函数这种写法,说来惭愧,以前在Java用过这种语法,心知C#也应该会有的,但在实际开发中从未使用过(因为偷懒,涉及CLR的当时懒得查,回头就忘了)。但静态构造函数在初始化静态数据时确实很有作用,省去了对象初始化时的判断操作(我之前就是这样一直偷懒的)。
以下是VisualStudio自动生成的模板代码:
语法格式
class User
{
// 静态构造函数
static User()
{
// 你的代码
}
}
用法与特性
主要作用
- 执行仅需执行一次的特定操作。
- 初始化任何静态数据。
理论上,一个静态构造函数在一个应用程序的完整生命周期中,最多
只会被自动
执行一次。
之所以说“自动
”,是因为静态构造函数的执行是由CLR完成的。
之所以说“最多
”,是因为CLR将在创建第一个实例
或引用任何静态成员
之前自动调用静态构造函数。
语法特性
- 静态构造函数不允许使用访问修饰符。
- 静态构造函数必须无参数。
- 一个类(或结构体)只能有一个静态构造函数。
- 静态构造函数不能继承或重载。
- 静态构造函数只允许被公共语言运行时 (CLR) 自动调用,不允许直接调用。
- 不同类型的静态构造函数执行的顺序与运行时调用的顺序有关。
关于泛型的测试
如果使用了泛型,指定不同的类型是否会多次触发静态构造函数呢?
对此写了一个代码进行测试。
测试代码
// 测试类型1号
class Test<T>
{
public static int Value { get; set; }
static Test()
{
Console.WriteLine($"执行【静态构造函数】,类型为:{typeof(Test<T>)}");
}
public Test()
{
Console.WriteLine($"执行【普通构造函数】,类型为:{this.GetType()},值为:{Value}");
}
}
// 测试类型2号
class User
{
static User()
{
Console.WriteLine("未引用到的类型不会被执行。");
}
}
Program.cs中测试代码如下:
new Test<int>();
new Test<int>();
new Test<int>();
Console.WriteLine();
new Test<long>();
Console.WriteLine();
Test<short>.Value = 10;
Console.WriteLine();
Test<double>.Value = 20;
new Test<double>();
Console.ReadLine();
运行结果
命令行窗口截图:
由此可以看出,指定不同的泛型类型,其静态构造函数是相互独立的;
另外,User类型未被调用过,所以没有执行静态构造函数,也就没有对应的打印输出。