我们知道在C#语言中创建一个类型的实例前,就应该初始化该类型的所有静态成员变量。C#语言为我们提供了静态初始化器和静态构造函数。其中,静态构造函数是一个特殊的构造函数,将在其他所有方法执行前以及变量或属性被第一次访问之前将自动调用静态构造函数,且仅执行一次。我们可以通过使用静态构造函数来初始化静态变量、实现单例模式或者执行类在可用之前的所有操作。但是不能够使用实例构造函数专门的私有函数或者其他什么方式来初始化静态变量。

  静态类成员变量也有和实例成员类似的初始化器语法,如果只是需要为某个静态成员分配空间,可以直接使用初始化器语法,但是如果需要使用一些更复杂的逻辑来初始化静态成员变量那就应该直接使用静态构造函数。

1.单例模式中的静态构造函数

  在C#中实现单例模式是静态构造函数的一个常见场景。只需要将实例构造函数声明为私有,然后添加一个初始化器即可:

     public class Singleton
{
/// <summary>
/// 静态成员变量,添加 readonly 关键字
/// </summary>
private static readonly Singleton theOneAndOnly = new Singleton(); /// <summary>
/// 只读的静态属性
/// </summary>
public static Singleton TheOnly
{
get { return theOneAndOnly; }
} /// <summary>
/// 私有的实例构造函数
/// </summary>
private Singleton()
{
}
}

编译器生成的代码类似于下面:

     public class Singleton
{
/// <summary>
/// 静态成员变量,添加 readonly 关键字
/// </summary>
private static readonly Singleton theOneAndOnly; /// <summary>
/// 只读的静态属性
/// </summary>
public static Singleton TheOnly
{
get { return theOneAndOnly; }
} /// <summary>
/// 静态构造函数
/// </summary>
static Singleton()
{
theOneAndOnly = new Singleton();
} /// <summary>
/// 私有的实例构造函数
/// </summary>
private Singleton()
{
}
}

和实例初始化器类似,静态初始化器在任何静态构造函数之前执行。而且,静态初始化器在调用基类的静态构造函数之前执行。

2.关于静态构造函数

  静态构造函数用于初始化任何静态数据,在创建第一个实例或者引用任何静态成员之前,静态构造函数将会被CLR调用来初始化类,且仅调用一次。

静态构造函数具有如下特点

  • 静态构造函数既没有访问修饰符也不接受任何参数
  • 在创建第一个实例或者引用任何静态成员之前,静态构造函数将会被CLR调用来初始化类
  • 不能直接调用静态构造函数,并且在程序中不受控制
  • 如果静态构造函数引发异常,CLR将不会尝试再次调用该构造函数,在应用程序作用域(AppDomain)内,类型将保持未初始化,这会导致该类及其派生类创建的类型没有得到完全初始化

3.静态初始化器&静态构造函数

  通过前面关于静态构造函数的特点,我们知道:如果静态构造函数引发异常,在该次应用程序作用域(AppDomain)内CLR将不会尝试再次调用该构造函数,这会导致该类及其派生类创建的类型没有得到完全初始化。

  如果直接只用静态初始化器语法:编译器会添直接将静态成员初始化代码加入到静态构造函数中,并且没有任何异常处理。所以在使用静态初始化器时,我们无法捕获并处理异常。然而在我们可以直接在静态构造函数中添加try/catch代码块了进行异常处理。如下:

     public class Singleton
{
/// <summary>
/// 静态成员变量,添加 readonly 关键字
/// </summary>
private static readonly Singleton theOneAndOnly; /// <summary>
/// 只读的静态属性
/// </summary>
public static Singleton TheOnly
{
get { return theOneAndOnly; }
} /// <summary>
/// 直接在静态构造函数中进行异常处理
/// </summary>
static Singleton()
{
try
{
theOneAndOnly = new Singleton();
}
catch
{
//......
}
} /// <summary>
/// 私有的实例构造函数
/// </summary>
private Singleton()
{
}
}

小节:

  静态初始化器和静态构造函数是初始化静态成员的最佳选择,容易理解并且不易出错。在其他语言中,这两个特性也是专门用来方便初始化静态成员而提供的。如果你需要在你的代码初始化静态成员的代码中进行异常处理是可以直接使用静态构造函数,在构造函数中添加异常处理代码;如果是只需要对静态成员进行空间的分配那么直接使用初始化器语法即可——在声明静态成员的时候对其进行初始化。

《Effective C#》读书笔记——条目13:正确地初始化静态成员变量<.NET资源管理>的更多相关文章

  1. Effective STL 读书笔记

    Effective STL 读书笔记 标签(空格分隔): 未分类 慎重选择容器类型 标准STL序列容器: vector.string.deque和list(双向列表). 标准STL管理容器: set. ...

  2. Effective STL读书笔记

    Effective STL 读书笔记 本篇文字用于总结在阅读<Effective STL>时的笔记心得,只记录书上描写的,但自己尚未熟练掌握的知识点,不记录通用.常识类的知识点. STL按 ...

  3. Effective Java读书笔记完结啦

    Effective Java是一本经典的书, 很实用的Java进阶读物, 提供了各个方面的best practices. 最近终于做完了Effective Java的读书笔记, 发布出来与大家共享. ...

  4. effective c++读书笔记(一)

    很早之前就听过这本书,找工作之前读一读.看了几页,个人感觉实在是生涩难懂,非常不符合中国人的思维方式.之前也有博主做过笔记,我来补充一些自己的理解. 我看有人记了笔记,还不错:http://www.3 ...

  5. 深入理解linux网络技术内幕读书笔记(八)--设备注册与初始化

    Table of Contents 1 设备注册之时 2 设备除名之时 3 分配net_device结构 4 NIC注册和除名架构 4.1 注册 4.2 除名 5 设备初始化 6 设备类型初始化: x ...

  6. 《C#高效编程》读书笔记12-使用推荐成员初始化器而不是赋值语句

    通常来说类都有不止一个构造函数.随着时间推移,成员变量的增加,构造函数的个数也会不断的增加.预防这种情况的最好方法是,在声明变量的时候就进行初始化,而不是在每个构造函数中进行. //初始化变量时声明 ...

  7. Effective C++读书笔记(转)

    第一部分 让自己习惯C++ 条款01:视C++为一个语言联邦 一.要点 ■ c++高效编程守则视状况而变化,取决于你使用c++的哪一部分. 二.扩展 将c++视为一个由相关语言组成的联邦而非单一语言会 ...

  8. Effective java读书笔记

    2015年进步很小,看的书也不是很多,感觉自己都要废了,2016是沉淀的一年,在这一年中要不断学习.看书,努力提升自己 计在16年要看12本书,主要涉及java基础.Spring研究.java并发.J ...

  9. Effective Objective-C 读书笔记

    一本不错的书,给出了52条建议来优化程序的性能,对初学者有不错的指导作用,但是对高级阶段的程序员可能帮助不是很大.这里贴出部分笔记: 第2条: 使用#improt导入头文件会把头文件的内容全部暴露到目 ...

随机推荐

  1. Shell--基础知识

    变量的定义: a=1 b=hello c="hello world !" d='hello "反启" !' e=`ls`  (注意:这是反引号) 备注:=号左右 ...

  2. 测试命令运行时间:timeit和profile

    先说timeit from timeit import Timer def test1(): n=0 for i in range(101): n+=i return n def test2(): r ...

  3. HDU5086:Revenge of Segment Tree(规律题)

    http://acm.hdu.edu.cn/showproblem.php?pid=5086 #include <iostream> #include <stdio.h> #i ...

  4. 整数(质因子)分解(Pollard rho大整数分解)

    整数分解,又称质因子分解.在数学中,整数分解问题是指:给出一个正整数,将其写成几个素数的乘积的形式. (每个合数都可以写成几个质数相乘的形式,这几个质数就都叫做这个合数的质因数.) .试除法(适用于范 ...

  5. 全自动照片美化软件Photolemur mac特别版

    今天小编为大家带来的是世界上首个支持全自动照片美化的软件Photolemur mac特别版.Photolemur中文特别版采用了全新的人工智能AI系统,它能够全自动智能的对您的照片进行曝光.亮度.降噪 ...

  6. Liferay portlet首选项(preferences)设置、存储处理

    最近使用Liferay做项目集成,由于团队人员在之前对Liferay这东西都没有充分的了解,用起来着实费了不少力气,最近为了为定制好的portlet添加初始化信息,翻阅了一些文章,下面是了解到的关于初 ...

  7. python中的TCP及UDP

    python中是通过套接字即socket来实现UDP及TCP通信的.有两种套接字面向连接的及无连接的,也就是TCP套接字及UDP套接字. TCP通信模型 创建TCP服务器 伪代码: ss = sock ...

  8. 梅尔频率倒谱系数(MFCC) 学习笔记

    最近学习音乐自动标注的过程中,看到了有关使用MFCC提取音频特征的内容,特地在网上找到资料,学习了一下相关内容.此笔记大部分内容摘自博文 http://blog.csdn.net/zouxy09/ar ...

  9. 【图像处理】计算Haar特征个数

    http://blog.csdn.net/xiaowei_cqu/article/details/8216109 Haar特征/矩形特征 Haar特征本身并不复杂,就是用图中黑色矩形所有像素值的和减去 ...

  10. JAVA volatile 解析

    volatile这个关键字可能很多朋友都听说过,或许也都用过.在Java 5之前,它是一个备受争议的关键字,因为在程序中使用它往往会导致出人意料的结果.在Java 5之后,volatile关键字才得以 ...