转:《Effective C#》Item 8:确保“0”在值类型中是有效的

转载 2007年09月30日 11:04:00

转:http://dev.csdn.net/author/Knight94/ba5bdb944fa049d4a990ba1bca067993.html

《Effective C#》Item 8:确保“0”在值类型中是有效的

 

大家在看了这标题后,肯定会觉的,为什么要确保“0”是有效的,这一点主要是跟值类型的内存分配有关,值类型有默认的构造函数,这是没法避免的,因此值类型变量中的成员在初始化的时候所出现的细微问题(对于值类型这方面的知识可以参看我前面一篇文章)。

http://blog.csdn.net/Knight94/archive/2006/07/01/861383.aspx

 

日常中比较常见的两种值类型,一个是enum定义的枚举类型,一个是用struct定义的数据类型。那我接下来就分别说明这两种类型如果不定义“0”为一个有效值的所能造成的后果,再分别说明如何加以修改来弥补这类错误。

 

对于enum定义的枚举类型来说,默认的起始值为0,但是如果在定义的时候,按照如下的方式去定义的话,有时候会造成意想不到的错误。

        public enum ERROR_CODE

        {

            INVALID_FILE_NAME       = 1001,

            CANT_BE_ACCESS          = 1002,

        }

 

如上的定义是没有默认值0的,那么当我显示的去定义一个此类型变量,例如:

        ERROR_CODE myError = new ERROR_CODE();

        Debug.WriteLine( string.Format( "{0}", (int)myError ) );

 

可以看出如上的输出结果是0,但是它不是一个有效的值,也许这种错误可能很少出现,但是在struct复合类型中这种错误表现得更为明显。例如:

        public struct ErrorMsg

        {

            private ERROR_CODE err;

            private string strMsg;

 

            // other properties or methods here

        }

 

对于如上的结构类型来说,由于默认构造函数存在,所以当创建一个ErrorMsg变量的时候,那么对于err这个成员的值是无效的。有人可能会说,增加构造函数来限制等等的做法来避免这类错误。那么为什么与其在ErrorMsg中增加限制,不如在定义ERROR_CODE的时候就避免呢。其实这类错误的避免方法很简单,只要在ERROR_CODE中增加0的有效定义即可,例如比较正确形式的应该如下:

        public enum ERROR_CODE

        {

            NO_ERROR                = 0,

            INVALID_FILE_NAME       = 1001,

            CANT_BE_ACCESS          = 1002,

        }

 

按照如上的做法就可以避免定义ERROR_CODE变量或者被组合到别的类型中的时候,都不会发生初始值是无效的尴尬局面。

 

在这本书中,对于枚举类型还提到一点,就是增加Flags标记的时候,一定要以None作为0,例如:

        [Flags]

        public enum Style

        {

            None        = 0,

            Flat        = 1,

        }

 

这样的目的是为了在与和或操作的时候能有意义。这方面的例子我就不多说了,例如:某个connection的状态,或者文件的某种属性等等都会用到类似的做法。

 

除了枚举类型外,对于struct定义的值类型来说,如果struct类型所包含的成员类型都是值类型的话,是没有什么问题(如果是自定义枚举类型,要参照上面所说的方法进行处理);但是如果包含引用类型,则需要进行初始化,避免在访问的时候出现异常。例如对于前面所说的ErrorMsg来说,由于struct默认构造函数的存在,有可能在ErrorMsg类型变量在构造后,其的strMsg成员不是有效的。除了string类型外,常见的还有数组类型。如何避免类似的问题呢,方法是采用属性来实现。例如:

        public struct ErrorMsg

        {

            private ERROR_CODE err;

            private string strMsg;

            public string Message

            {

                get

                {

                    if( strMsg == null ) return string.Empty;

                    else

                        return strMsg;

                }

            }

            // other properties or methods here

        }

 

        public struct IntArray

        {

            private int[] nArray;

            public int[] Array

            {

                get

                {

                    if( nArray == null )

                        nArray = new int[10];

                    return nArray;

                }

            }

        }

 

所以在论坛上经常看到有人提出不能在struct中定义一个固定维数的数组,那么参照如上的方法,这类问题就能得到很好地解决。

 

最后再提一句,对于要确保“0”在所定义的值类型中是有效的这一点来说别小看。屏蔽错误从细微做起,而且好的编码习惯会使后面的工作事半功倍。

 

 

Effective C# Item6:明辨值类型和引用类型的使用场合

可能是受到Java的影响,我在转向C#后,一直没有注意区分过值类型和引用类型,不论是编写新代码还是重构旧代码时,如果发现有一些信息需要独立出来时,一直都是以新建类的方式进行,很少考虑使用结构体(我到目...

Effective Modern C++ : Item 8 -> 优先选择nullptr而不是0和NULL

优先选择nullptr而不是0和NULL 我们知道:0是一个int,而不是一个指针。如果C++在一个只有指针才能够使用的上下文中发现它只有一个0,那么它会勉强将0解释成空指针,但那时一种倒退行为。C...

Effective C# Item19:定义并实现接口优于继承类型

这个话题不仅仅是针对.NET的,在其他面向对象语言的环境中,例如Java,都会有接口和抽象类,对于究竟是选择接口还是抽象类,已经有了太多的讨论,包括设计模式中都有了一条设计原则:组合优于继承,虽然这条...

Effective C#阅读笔记-6Prefer Immutable Atomic Value Types不可变值类型

Prefer Immutable Atomic Value Types不可变值类型:一旦创建,将不会变化(constant),不能改变object内部状态。 对于不可变值类型有以下的好处: 1.多线程...

Item 8:析构函数不要抛出异常 Effective C++笔记

Item 8: Prevent exceptions from leaving destructors. 析构函数不要抛出异常 由于析构函数常常被自动调用,在析构函数中抛出的异常往往会难以...
  • yangjvn
  • yangjvn
  • 2015年08月24日 13:20
  • 678

Effective C++ Item 8 别让异常逃离析构函数

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验1: 析构函数绝对不要吐出异常。如果一个被析构函数调用的...

【Effective Java】Ch3_Methods:Item8_重写equals方法时遵循通用约定

虽然Object类是一个具体类,但它主要还是用于扩展。因为其所有nonfinal方法(equals、hashCode、toString、clone以及finalize)都是为重写设计的,所以这些方法都...

c#2_0不完全类型(转)

  • 2011年11月09日 15:53
  • 9KB
  • 下载

Item 24:用非成员函数来支持所有元的类型转换 Effective C++笔记

Item 24: Declare non-member functions when type conversions should apply to all parameters. 虽然I...
  • yangjvn
  • yangjvn
  • 2015年09月10日 05:12
  • 564

《More Effective C++》 Item M2:尽量使用C++风格的类型转换

c++有四种类型转换:static_cast、const_cast、dynamic_cast、reinterpret_cast。 1.static_cast(expression) static_...
  • sdauzxl
  • sdauzxl
  • 2016年04月12日 10:35
  • 133
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:转:《Effective C#》Item 8:确保“0”在值类型中是有效的
举报原因:
原因补充:

(最多只允许输入30个字)