《Effective C#》Item 13:使用静态构造函数初始化静态成员

来源:互联网 发布:原生js面向对象写法 编辑:程序博客网 时间:2024/05/17 07:41

编写程序的时候难免要使用到静态成员,由于静态成员的访问是脱离类型对象的,所以使用非静态构造函数,私有方法或者一些其他方法都是不合理的。.Net提供了成员初始化语句和静态构造函数来初始化静态成员。

 

根据上一个单元,我们可以知道静态成员的初始化语句会早于静态构造函数执行,其次还知道成员初始化语句的好处和一些限制。这里要提的一点就是,静态构造函数和实例构造函数之间的区别,因为静态构造函数是由CLR调用执行的,所以静态构造函数只能是一个,同时不能还有参数。那么静态构造函数相对于成员初始化的一些弊端都不复存在。

 

此外,对于成员初始化最大的问题,就是异常无法捕获,可能对于普通成员来说,还可以在构造类型对象的时候加上try-catch;而对于静态成员来说,有时无法确定哪一个类型访问语句会先执行,如果对每个使用类型的地方都加上try-catch,会降低程序可读性。但如果把这种异常散发出去,会导致整个程序崩溃。那么使用静态构造函数就能比较好的捕获异常,并进行异常处理。

 

对于静态成员初始化语句和静态构造函数一个对比大致如下。

 

简便性

安全性

异常处理

静态成员初始化

最简便

比较安全

非常难

静态构造函数

比较简便

最安全

容易

 

那么到底用什么方法来初始化静态成员呢,给出以下两点建议。

第一就是简单静态成员,例如类型为值类型等,使用成员初始化语句来完成;

第二静态成员初始化比较复杂,或者有可能出现异常,那么用静态构造函数来完成。

 

本单元的内容基本上讲完了,现在说说静态成员最主要的一个应用“Singleton”,就是保证此类型的对象唯一性。其实实现很简单,如下就举一个简单的例子。

        public class MySingleton

        {

            private static readonly MySingleton _theOneAndOnly;

 

            static MySingleton()

            {

                _theOneAndOnly = new MySingleton();

            }

 

            public static MySingleton TheOnly

            {

                get{ return _theOneAndOnly; }

            }

 

            /// <summary>

            /// Private constructor to avoid object created from outside

            /// </summary>

            private MySingleton()

            {

            }

        }

 

对于静态成员何时被初始化,其实仔细看我上一个单元所说的对象构造步骤就可以分析出来。可能看起来比较抽象,尤其在分析嵌套关系的时候,现在就举一个例子来进行说明。

    class A

    {

        public static int X = B.Y;

        static A()

        {

            ++X;

        }

    }

 

    class B

    {

        public static int Y = A.X;

        static B()

        {

            ++Y;

        }

    }

 

那么大家先猜猜如下调用输出结果是什么。

    Debug.WriteLine( A.X.ToString() );

    Debug.WriteLine( B.Y.ToString() );

 

其结果是“21”,也就是A.X的值为2,而B.Y的值为1

分析此类问题,只要记住三点就行了。

第一代码的执行顺序,代码在前的先执行;

第二静态成员初始化语句要先于静态构造函数执行;

第三静态成员初始化语句与静态构造函数只执行一次。

 

如果了解这三点,接下来就分析为什么会出现上面的结果。

当调用到第一条语句的时候,

Debug.WriteLine( A.X.ToString() );

首先是访问A这个类型,那么要对A这个类型的静态成员进行初始化,其次如果有静态构造函数,需要调用它。

对于A的静态成员只有“X”,按照上一单元的过程,先给其分配空间,并辅以0来初始化,其次调用其对应的成员初始化语句来初始化这个静态成员。

那么它的成员初始化语句是“X = B.Y”,那么需要访问“B.Y”来初始化X这个静态成员。

对于“B.Y”的访问,就是访问B类型,也是和访问A一样,首先对这个类型的静态成员进行初始化,其次如果有静态构造函数,需要调用它。而B的静态成员只有“Y”,先给其分配空间,并辅以0来初始化,其次调用其对应的成员初始化语句来初始化这个静态成员。

那么对于“Y = A.X”成员初始化语句,由于此时不是第一次访问类型A,所以不再进行静态成员初始化和静态构造函数的调用,对于“A.X”的访问是直接访问。此时“A.X”的值为0,那么Y的值也为0;接着执行B的静态构造函数,这样处理后Y的值为1

那么对于A中的成员初始化语句“X = B.Y”,到此就执行完了,此时A类型中的XB类型中的Y都是一样的,值为1。不过B中的静态成员初始化语句和静态构造函数都执行过了,而A中的静态构造函数还未执行。因此经过A的静态构造函数处理,AX值为2,这也就是最后显示的结果。

 

分析过程看起来很绕,其实只要把握我前面所说的三个原则,那么在复杂的问题也一样分析 
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 excel打印太小怎么办 工地临时人员死亡怎么办 哺乳期乳腺增生疼怎么办 哺乳期有乳腺增生怎么办 哺乳期得了乳腺增生怎么办 中等教育认证花名册丢失怎么办 哺乳期囊性结节怎么办 乳腺增生堵奶怎么办 月子期乳房增生怎么办 母乳期乳腺增生怎么办 上市公司破产了股票怎么办 iptv错误码30022怎么办 电信iptv不清晰怎么办 电信iptv卡顿怎么办 pr滚动字幕闪烁怎么办 电视车表盘看不清怎么办 图片字看不清楚怎么办 字太潦草看不清怎么办 微信图片看不清怎么办 小车上坡没动力怎么办 上海牌照拍到了怎么办 杭州车牌摇不到怎么办 孩子不上进家长怎么办 孩子读书蠢以后怎么办 上海银行储蓄卡怎么办 分数不够读高中怎么办 iso11.4耗电快怎么办 支票存根联丢失怎么办 注册公司没有办公室怎么办 收款条一方有怎么办 员工收款跑了怎么办 社保转外地医保怎么办 异地辞职后医保怎么办 公司交深圳保险怎么办 异地办社保医保怎么办 个人异地交社保怎么办 终止挂牌股民钱怎么办 终止挂牌后股票怎么办 创建下载目录失败怎么办 应用未被唤起怎么办 银行卡存款满了怎么办