原则13:使用恰当的方式对静态成员进行初始化

优质
小牛编辑
132浏览
2023-12-01

你应该知道静态成员变量在创建对象实例之前就已经初始化了。C# 提供了静态初始化语法和静态构造函数对静态成员变量进行初始化。静态构造函数是一个比其他函数,变量,属性在没有访问之前就被执行的特殊函数。你可以使用这个函数初始化静态变量,完善单例模式,或者任何需要在类还没有被使用的必要工作。你不能使用构造函数,一些特殊 private 函数,或其他语法初始化静态变量。

和实例初始化一样,初始化语法是静态构造函数的另一选择。你只需要声明一个静态成员,然后使用初始化语法。如果有静态变量的初始化逻辑很复杂,你可以创建一个静态构造函数。

C# 实现单例模式最常用的方法就是静态构造函数。让构造函数变为 private ,然后添加一个初始化语法:

public class MySingleton 
{
    private static readonly MySingleton theOneAndOnly = new MySingleton();
    public static MySingleton TheOnly 
    {
        get { return theOneAndOnly; } 
    }
    private MySingleton() 
    { 
    }
    // remainder elided 
}

单例模式很容易像上面的方式一样实现。如果初始化逻辑更复杂:

public class MySingleton2 
{
    private static readonly MySingleton2 theOneAndOnly;
    static MySingleton2()
    {
        theOneAndOnly = new MySingleton2();
    }
    public static MySingleton2 TheOnly 
    {
        get { return theOneAndOnly; } 
    }
    private MySingleton2() 
    { 
    }
    // remainder elided 
}

和实例初始化一样,静态初始化语法在任何静态构造函数之前执行。并且,你的静态初始化语法比基类的静态构造函数更早执行。

CLR 在类型第一次在应用空间被访问之前自动执行静态构造函数。你只能定义一个静态构造函数,并且不能有参数。因此你需要注意在静态构造函数是否会产生异常。如果你在静态构造函数抛出了异常, CLR 会终止你的程序。这种情况捕获异常是非常阴险的。这时的代码区创建这个类型就会失败直到 AppDomain 被卸载。 CLR 就不能执行静态构造函数去初始化这个类型。即使你再尝试,类型不会被正确初始化。创建这个类型的对象(或者任意子类)都是没有被定义的。所以,这是不允许的。

异常是使用静态构造函数代替静态初始化语法的最常见原因。因为你使用静态初始化语法,你不能自己捕获异常。使用静态构造函数,你就可以(查看原则47:):

 static MySingleton2() 
{
    try 
    {
        theOneAndOnly = new MySingleton2(); 
    } 
    catch 
    {
        // Attempt recovery here. 
    }
}

静态初始化语法和静态构造函数是最干净,最清晰的方式去初始化静态成员变量。它们具有很强的可读性和很容易正确使用。它们被支持就是为了解决这个其他语言初始化静态成员会出现的问题。

小结:

这个事情一直拖着,一直想继续,今天又起了个头了,希望能一鼓作气。翻译很烂并且有很多不明确的地方(自己读的疑惑),算是给自己买下一个伏笔吧,还有很多工作要去完善。

欢迎各种不爽,各种喷,写这个纯属个人爱好,秉持”分享“之德!