大家在看了這標題後,肯定會覺的,爲什麼要確保“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”在所定義的值類型中是有效的這一點來說別小看。屏蔽錯誤從細微做起,而且好的編碼習慣會使後面的工作事半功倍。