《Effective C#》读书笔记——条目12:推荐使用成员初始化器而不是赋值语句<.NET资源管理>

简介:

 一般情况下,一个类都会有多个构造函数。随着时间的推移,成员变量、构造函数不断增加。为了处理这种情况最方便的办法就是:在声明变量的时候进行初始化,而不是在每个构造函数中进行。无论是类成员(静态变量)合适实例变量,我们都应该充分利用初始化器的语法。

  C#编程在,一般在声明一个变量的同时我们会对其进行初始化:

1     class Employee
2     {
3         private List<Employee> empList = new List<Employee>();
4     }

不论我们为Employee类添加了多少个构造函数,empList变量都能够被正确的初始化,这是因为:

编译器会在所有的构造函数(包括默认构造函数)的最开始位置生成代码来为所以的实例成员变量定义初始化器(进行初始化);所以我们不需要再构造函数中为每一个定义的成员变量添加初始化代码——直接在声明的时候初始化即可。

  初始化器可以看做是构造函数中初始化语句的另一种表示。初始化器生成的代码会插入到构造函数代码前面执行。初始化器将在为类型执行调用基类构造函数之前执行,其顺序与类成员变量声明的顺序一样。

  C#的初始化器语法是一种最简单的、能够避免类型中存在未初始化变量的解决办法。但是在下面的三种情况下应该避免使用初始化器:

1.初始化对象为0或null时

   因为系统默认的初始化会将会在所有代码执行前把一切都设置成0或者null(值类型和引用类型)。而且这一步的操作是位于很底层的实现,我们也可以直接将对象赋值设置为0或null,但是显然这是多余的。

 

2.对同一个变量执行不同的初始化方式

   使用初始化语句的一个前提是:所有得构造函数都将为该变量设置同样的值。我们看下面的示例代码:

复制代码
 1     class Employee
 2     {
 3         //声明变量的同时进行初始化
 4         private List<Employee> empList = new List<Employee>();
 5 
 6         public Employee()
 7         {
 8         }
 9 
10         public Employee(int size)
11         {
12             empList = new List<Employee>(size);
13         }
14     }
复制代码

 

在上面的代码中,当我们调用第二个构造函数创建初始化指定大小的泛型集合时 ,实际上时创建了两个List<Employee>。第一个创建后马上变成了垃圾——这是由于初始化器将在所有构造函数之前执行。编译器生成的代码类似于下面的这段代码:

复制代码
 1     class Employee
 2     {
 3         //声明变量
 4         private List<Employee> empList;
 5 
 6         public Employee()
 7         {
 8               empList = new List<Employee>();
 9         }
10 
11         public Employee(int size)
12         {
13             empList = new List<Employee>();
14             empList = new List<Employee>(size);
15         }
16     }
复制代码

 我们可以看到这样做会影响程序的效率,创建了不必要的对象,所以如果需要在不同的构造函数中执行不同的初始化方式时正确的做法应该是不适用初始化器,而是先声明变量,然后在构造函数中进行成员变量的初始化,如下:

复制代码
 1      class Employee
 2      {
 3          //声明变量
 4          private List<Employee> empList;
 5  
 6          public Employee()
 7          {
 8                empList = new List<Employee>();
 9          }
10  
11          public Employee(int size)
12          {
13              empList = new List<Employee>(size);
14          }
15      }
复制代码

 

3.需要进行异常处理

   初始化器无法被try语句包裹。所以对象初始化器执行的过程中发生异常都会被传递到对象之外。如果在初始化对象的时候可能会抛出异常时我们应该将这部分代码放到构造函数中,对其进行异常处理。这样才能够实现必要的恢复性代码,以创建类型实例并以更友好的方式处理异常。

 

小节:

  成员初始化器是保证类型中成员变量都被初始化的最简单方法——在声明变量时就对其进行初始化,无论调用的是那个构造函数,初始化器都将会在所有构造函数之前执行。这种语法也避免了在添加新的构造函数时遗漏掉重要的初始化代码。所以,如果对于所有的构造函数某个成员变量的初始化值是一样的,那么就应该尽量使用初始化器语法。

 

本文转自gyzhao博客园博客,原文链接:http://www.cnblogs.com/IPrograming/archive/2012/11/06/Effective_CSharp_12.html ,如需转载请自行联系原作者
相关文章
《More Effective C# 》读书笔记 第一章
《More Effective C# 》读书笔记 第一章
|
存储 程序员 编译器
【Effective C++详细总结】第三章 资源管理
【Effective C++详细总结】第三章 资源管理
253 0
|
API C++
读书笔记 effective c++ Item 15 在资源管理类中提供对原生(raw)资源的访问
1.为什么需要访问资源管理类中的原生资源  资源管理类是很奇妙的。它们是防止资源泄漏的堡垒,没有资源泄漏发生是设计良好的系统的一个基本特征。在一个完美的世界中,你需要依赖这样的类来同资源进行交互,绝不要直接访问原生(raw)资源而玷污你的双手。
982 0
|
C++
读书笔记 effective c++ Item 14 对资源管理类的拷贝行为要谨慎
1. 自己实现一个资源管理类  Item 13中介绍了 “资源获取之时也是初始化之时(RAII)”的概念,这个概念被当作资源管理类的“脊柱“,也描述了auto_ptr和tr1::shared_ptr是如何用堆资源来表现这个概念的。
1076 0
|
C++ 容器
读书笔记 effective c++ Item 13 用对象来管理资源
1.不要手动释放从函数返回的堆资源 假设你正在处理一个模拟Investment的程序库,不同的Investmetn类型从Investment基类继承而来, 1 class Investment { .
1032 0
|
C++ 编译器 安全
读书笔记 effective c++ Item 12 拷贝对象的所有部分
1.默认构造函数介绍 在设计良好的面向对象系统中,会将对象的内部进行封装,只有两个函数可以拷贝对象:拷贝构造函数和拷贝赋值运算符。我们把这两个函数统一叫做拷贝函数。从Item5中,我们得知,如果需要的话编译器会为你生成这两个拷贝函数,并且编译器生成的版本能够精确的做到你想做的:它们拷贝了对象的所有数据。
845 0
|
C++ 安全 C#
读书笔记 effective c++ Item 9 绝不要在构造函数或者析构函数中调用虚函数
1.关于构造函数的一个违反直觉的行为 我会以重复标题开始:你不应该在构造或者析构的过程中调用虚函数,因为这些调用的结果会和你想的不一样。如果你同时是一个java或者c#程序员,那么请着重注意这个条款,因为这是c++同它们不一样的地方。
935 0
|
安全 C++ Python
读书笔记 effective c++ Item 11 在operator=中处理自我赋值
1.自我赋值是如何发生的 当一个对象委派给自己的时候,自我赋值就会发生: 1 class Widget { ... }; 2 3 Widget w; 4 5 ... 6 7 w = w; // assignment to self、 这看上去是愚蠢的,但这是合法的,所以请放心,客户端是可以这么做的。
1020 0
|
C++ 容器 数据库连接
读书笔记 effective c++ Item 8 不要让异常(exceptions)离开析构函数
1.为什么c++不喜欢析构函数抛出异常 C++并没有禁止析构函数出现异常,但是它肯定不鼓励这么做。这是有原因的,考虑下面的代码: 1 class Widget { 2 3 public: 4 5 .
832 0
|
C++ 编译器 安全
读书笔记 effective c++ Item 6 如果你不想使用编译器自动生成的函数,你需要明确拒绝
问题描述-阻止对象的拷贝   现实生活中的房产中介卖房子,一个服务于这个中介的软件系统很自然的会有一个表示要被销售的房屋的类: 1 class HomeForSale { ... };   每个房产中介会立刻指出来,要销售房屋的每个属性都是唯一的,没有两个完全一样的房屋。
833 0