《Effective C#》读书笔记——条目19:保证0为值类型的有效状态<.NET资源管理>

简介:

NET系统的默认初始化过程会将所有的对象设置为0。我们就会难免创建出一个初始化为0值的值类型,所以我们应该将0作为类型的默认值,可以避免一些不必要的Bug。

 

1.将0设置为枚举的有效值

  使用枚举时我们必须将0设置为枚举的一个有效选项。所以枚举值都派生于System.ValueType。枚举默认的值开始于0,但是也可以自定义:

复制代码
1     public enum Month
2     {
3         //枚举的默认值是从0开始
4         Jan = 1,
5         Feb = 2,
6         Mar = 3,
7         April = 4,
8         May = 5,
9     }
复制代码

 但是如果实例化一个Month,我们将会得到一个为0的默认值,而这并不是Month的合法值:

1         Month month = new Month();
2         Console.WriteLine((int)month);
3         //输出0

 因此在创建自定义的枚举的时候,必须确保0是一个合法的有效选项,如果可能应该将最适合做默认值的选项表示0,如果没有合适的选项适合做默认值的话,可以把0表示未初始化的值(逻辑上),让类型的使用者知道它当前的状态,例如修改成下面这样:

复制代码
 1     public enum Month
 2     {
 3         //枚举的默认值是从0开始
 4         None = 0,
 5         Jan = 1,
 6         Feb = 2,
 7         Mar = 3,
 8         April = 4,
 9         May = 5,
10     }
复制代码

 

2.正确初始化包含引用的值类型

   对于包含引用的值类型(如:字符串),也是比较在初始化的时候出现问题:

1     public struct LogMessage
2     {
3         private int ErrLevel;
4         private string msg;
5     }    

 

在上面的程序中, 如果实例化一个LogMessage对象,msg字段为一个空引用,且不能直接对其进行初始化(private访问修饰符),不过我们可以通过使用属性类解决这个问题,通过属性将msg字段暴露给外界使用者。然后在属性中添加逻辑:在msg为null是返回一个空字符串:

复制代码
 1     public struct LogMessage
 2     {
 3         private int ErrLevel;
 4         private string msg;
 5         
 6         public string LogMessage
 7         {
 8             get
 9             {
10                 return (msg! = null)?msg:string.Empty;
11             }
12             set
13             {
14                 msg = value;
15             }
16         }
17     }
复制代码

 这样做的好处就是将null引用的检查限制在一个单一的类型中,假如在程序集内部调用,那么Message属性很可能会被内联。这样既保证了代码的效率,也降低了错误发生的可能。

 

小节

  系统的初始化行为让所有的值类型的值都设置为0,这是我们无法避免的,我们能做的就是尽量将0设置为最可能的默认值,反正,也应该将0作为一个有效的合法选项,就行我们前面的第一个示例一样。

本文转自gyzhao博客园博客,原文链接:http://www.cnblogs.com/IPrograming/archive/2013/01/12/EffectiveCSharp_19.html ,如需转载请自行联系原作者
相关文章
|
8月前
|
C#
《More Effective C# 》读书笔记 第一章
《More Effective C# 》读书笔记 第一章
|
10月前
|
存储 程序员 编译器
【Effective C++详细总结】第三章 资源管理
【Effective C++详细总结】第三章 资源管理
231 0
|
存储 Java .NET
.NET面试题解析(01)-值类型与引用类型
转自:http://www.cnblogs.com/anding  常见面试题目: 1. 值类型和引用类型的区别? 2. 结构和类的区别? 3. delegate是引用类型还是值类型?enum、int[]和string呢? 4.
1105 0
|
API C++
读书笔记 effective c++ Item 15 在资源管理类中提供对原生(raw)资源的访问
1.为什么需要访问资源管理类中的原生资源  资源管理类是很奇妙的。它们是防止资源泄漏的堡垒,没有资源泄漏发生是设计良好的系统的一个基本特征。在一个完美的世界中,你需要依赖这样的类来同资源进行交互,绝不要直接访问原生(raw)资源而玷污你的双手。
943 0
|
C++
读书笔记 effective c++ Item 14 对资源管理类的拷贝行为要谨慎
1. 自己实现一个资源管理类  Item 13中介绍了 “资源获取之时也是初始化之时(RAII)”的概念,这个概念被当作资源管理类的“脊柱“,也描述了auto_ptr和tr1::shared_ptr是如何用堆资源来表现这个概念的。
1050 0
|
C++ 容器
读书笔记 effective c++ Item 13 用对象来管理资源
1.不要手动释放从函数返回的堆资源 假设你正在处理一个模拟Investment的程序库,不同的Investmetn类型从Investment基类继承而来, 1 class Investment { .
997 0
|
C++ 编译器 安全
读书笔记 effective c++ Item 12 拷贝对象的所有部分
1.默认构造函数介绍 在设计良好的面向对象系统中,会将对象的内部进行封装,只有两个函数可以拷贝对象:拷贝构造函数和拷贝赋值运算符。我们把这两个函数统一叫做拷贝函数。从Item5中,我们得知,如果需要的话编译器会为你生成这两个拷贝函数,并且编译器生成的版本能够精确的做到你想做的:它们拷贝了对象的所有数据。
822 0
|
C++ 安全 C#
读书笔记 effective c++ Item 9 绝不要在构造函数或者析构函数中调用虚函数
1.关于构造函数的一个违反直觉的行为 我会以重复标题开始:你不应该在构造或者析构的过程中调用虚函数,因为这些调用的结果会和你想的不一样。如果你同时是一个java或者c#程序员,那么请着重注意这个条款,因为这是c++同它们不一样的地方。
913 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、 这看上去是愚蠢的,但这是合法的,所以请放心,客户端是可以这么做的。
984 0
|
C++ 容器 数据库连接
读书笔记 effective c++ Item 8 不要让异常(exceptions)离开析构函数
1.为什么c++不喜欢析构函数抛出异常 C++并没有禁止析构函数出现异常,但是它肯定不鼓励这么做。这是有原因的,考虑下面的代码: 1 class Widget { 2 3 public: 4 5 .
804 0