Effective C# 原则13:用静态构造函数初始化类的静态成员
(译注:initializer在上文中译为了“初始化器”,实在不好听,本文中全部改译为:“预置方法”)\
你应该知道,在一个类型的任何实例初始化以前,你应该初始化它的静态成员变量。在里C#你可以使用静态的预置方法和静态构造函数来实现这个目的。一个类的静态构造函数是一个与众不同的,它在所有的方法,变量或者属性访问前被执行。你可以用这个函数来初始化静态成员变量,强制使用单件模式,或者实现其它任何在类型的实例可用前应该完成的工作。你不能用任何的实例构造函数,其它特殊的私有函数,
或者任何其它习惯方法来初始化一个
变量(译注:编译器就不让你这样做,所以你不用担心这样的问题)。
和实例的预置方法一样,你可以把静态的预置方法做为静态构造函数可替代的选择。如果须要简单的分配一个静态成员,就直接使用初始化语法。当你有更复杂的逻辑来初始化静态成员变量时,就创建一个静态构造函数:
public class MySingleton
{
private static readonly MySingleton _theOneAndOnly = new MySingleton( );
public static MySingleton TheOnly
{
get
{
return _theOneAndOnly;
}
}
private MySingleton( )
{
}
// remainder elided
}
可以用下面的方法简单的实现单件模式,实际上你在初始化一个单件模式时可能有更复杂的逻辑:
public class MySingleton
{
private static readonly MySingleton _theOneAndOnly;
static MySingleton( )
{
_theOneAndOnly = new MySingleton( );
}
public static MySingleton TheOnly
{
get
{
return _theOneAndOnly;
}
}
private MySingleton( )
{
}
// remainder elided
}
同样,和实例的预置方法一样,静态的预置方法在静态的构造函数调用前执行。并且,你的静态预置方法在基类的静态构造函数执行前被执行。
当应用程序第一次装载你的数据类型时,CLR自动调用静态构造函数。你只能定义一个静态构造函数,并且不能有参数。因为静态构造函数是CLR调用的,你必须十分注意异常的产生。如果在静态构造函数里产生了异常,CLR将会直接终止你的应用程序。正因为异常,静态构造函数常常代替静态预置方法。如果你使用静态预置方法,你自己不能捕获异常。做为一个静态的构造,你可以这样(参见原则45):
static MySingleton( )
{
try {
_theOneAndOnly = new MySingleton( );
} catch{
// Attempt recovery here.
}
}
静态预置方法和静态构造函数为你的类提供了最清爽的方法来初始化静态成员。与其它语言不同,它们被添加到C#语言中,是初始化静态成员的两个不同的特殊位置。