《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”在所定義的值類型中是有效的這一點來說別小看。屏蔽錯誤從細微做起,而且好的編碼習慣會使後面的工作事半功倍。

 

 
發佈了87 篇原創文章 · 獲贊 9 · 訪問量 100萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章