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

简介:

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

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

 

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

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

复制代码
 1     public class Singleton
 2     {
 3         /// <summary>
 4         /// 静态成员变量,添加 readonly 关键字
 5         /// </summary>
 6         private static readonly Singleton theOneAndOnly = new Singleton();
 7 
 8         /// <summary>
 9         /// 只读的静态属性
10         /// </summary>
11         public static Singleton TheOnly
12         {
13             get { return theOneAndOnly; }
14         }
15 
16         /// <summary>
17         /// 私有的实例构造函数
18         /// </summary>
19         private Singleton()
20         {
21         }
22     }
复制代码

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

复制代码
 1     public class Singleton
 2     {
 3         /// <summary>
 4         /// 静态成员变量,添加 readonly 关键字
 5         /// </summary>
 6         private static readonly Singleton theOneAndOnly;
 7 
 8         /// <summary>
 9         /// 只读的静态属性
10         /// </summary>
11         public static Singleton TheOnly
12         {
13             get { return theOneAndOnly; }
14         }
15 
16         /// <summary>
17         /// 静态构造函数
18         /// </summary>
19         static Singleton()
20         {
21             theOneAndOnly = new Singleton();
22         }
23 
24         /// <summary>
25         /// 私有的实例构造函数
26         /// </summary>
27         private Singleton()
28         {
29         }
30     }
复制代码

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

 

2.关于静态构造函数

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

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

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

 

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

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

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

复制代码
 1     public class Singleton
 2     {
 3         /// <summary>
 4         /// 静态成员变量,添加 readonly 关键字
 5         /// </summary>
 6         private static readonly Singleton theOneAndOnly;
 7 
 8         /// <summary>
 9         /// 只读的静态属性
10         /// </summary>
11         public static Singleton TheOnly
12         {
13             get { return theOneAndOnly; }
14         }
15 
16         /// <summary>
17         /// 直接在静态构造函数中进行异常处理
18         /// </summary>
19         static Singleton()
20         {
21             try
22             {
23                 theOneAndOnly = new Singleton();
24             }
25             catch
26             {
27                 //......
28             }
29         }
30 
31         /// <summary>
32         /// 私有的实例构造函数
33         /// </summary>
34         private Singleton()
35         {
36         }
37     }
复制代码

 

 

小节:

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

 

进一步阅读&参考资料

MSDN:静态构造函数

本文转自gyzhao博客园博客,原文链接:http://www.cnblogs.com/IPrograming/archive/2012/11/15/Effective_CSharp_13.html ,如需转载请自行联系原作者
相关文章
|
存储 C# 图形学
【Unity 3D】C#数据类型和变量、命名规范的讲解(附源码)
【Unity 3D】C#数据类型和变量、命名规范的讲解(附源码)
599 1
|
存储 C# 索引
C# 一分钟浅谈:变量与数据类型简介
【9月更文挑战第1天】在 C# 编程中,了解变量与数据类型至关重要。本文详细介绍了 C# 中的值类型(如整数、浮点数、布尔值等)和引用类型(如类、接口、数组、字符串)。通过示例代码展示了变量的声明与使用方法,并针对数据类型转换错误、变量未初始化及数值溢出等常见问题提供了解决方案。正确选择数据类型不仅能提升程序性能,还可避免潜在错误,有助于编写高质量代码。
390 48
|
Web App开发 C# Windows
一款.NET开源的Windows资源管理器标签页工具
一款.NET开源的Windows资源管理器标签页工具
335 5
|
程序员 C#
C#基础①——注释、变量、快捷键、Write() 和WriteLine()、ReadKey()和ReadLine()的区别
C#基础①——注释、变量、快捷键、Write() 和WriteLine()、ReadKey()和ReadLine()的区别
|
存储 C# 开发者
C# 编程基础:注释、变量、常量、数据类型和自定义类型
C# 编程基础:注释、变量、常量、数据类型和自定义类型
247 1
|
传感器 开发框架 JSON
聊聊 C# dynamic 类型,并分享一个将 dynamic 类型变量转为其它类型的技巧和实例
聊聊 C# dynamic 类型,并分享一个将 dynamic 类型变量转为其它类型的技巧和实例
807 0
|
存储 Java 编译器
C# 变量与参数详解
C# 变量与参数详解
296 0
|
开发框架 .NET 程序员
掌握C#语言的精髓:基础知识与实用技能详解(数据类型与变量+ 条件与循环+函数与模块+LINQ+异常+OOP)
掌握C#语言的精髓:基础知识与实用技能详解(数据类型与变量+ 条件与循环+函数与模块+LINQ+异常+OOP)
164 0
|
存储 C# 容器
掌握 C# 变量:在代码中声明、初始化和使用不同类型的综合指南
变量是用于存储数据值的容器。 在 C# 中,有不同类型的变量(用不同的关键字定义),例如: int - 存储整数(没有小数点的整数),如 123 或 -123 double - 存储浮点数,有小数点,如 19.99 或 -19.99 char - 存储单个字符,如 'a' 或 'B'。Char 值用单引号括起来 string - 存储文本,如 "Hello World"。String 值用双引号括起来 bool - 存储具有两个状态的值:true 或 false
391 2
|
存储 C# 开发工具
22.C# 中使用变量记录玩家创建的角色名:实现与游戏角色的互动
22.C# 中使用变量记录玩家创建的角色名:实现与游戏角色的互动
303 0