.Net系統默認所有的對象初始化時都為0。這並沒有提供一個方法來預防其他 程序員創建的值類型數據的實例在初始化是都是0。請讓你的數據類型默認值也 是0。
一個特殊情況是在枚舉類型數據中。決不要創建一個不包括0在內 的枚舉類型。所有的枚舉類型都是從System.ValueType派生的。枚舉類型的值是 從0開始的,但你可以改變這一行為:
public enum Planet
{
// Explicitly assign values.
// Default starts at 0 otherwise.
Mercury = 1,
Venus = 2,
Earth = 3,
Mars = 4,
Jupiter = 5,
Saturn = 6,
Neptune = 7,
Uranus = 8,
Pluto = 9
}
Planet sphere = new Planet();
sphere此時的值就是0,而這並不是一個有效的值。枚 舉類型的取值限制在所有列舉的值中,任何依懶這一(普通)事實的代碼都將無法 工作。當你為你的枚舉類型創建你自己的取值時,請確保0是當中的一個。如果 你的枚舉類型采用的是以位(bit)模式,把0定義為其它屬性不存在時的取值。
按照現在的情況,你迫使用戶必須精確的初始化值:
Planet sphere = Planet.Mars;
這將使包含 (Planet)這一類型的其它類型很難創建:
public struct ObservationData
{
Planet _whichPlanet; //what am I looking at?
Double _magnitude; // perceived brightness.
}
創建一個新ObservationData實例的用戶會創建一個不合法的 Planet成員:
ObservationData d = new ObservationData ();
最後創建的ObservationData的成員_magnitude的值是0,這 是合理的。但_whichPlanet卻是無效的。你須要讓0也是有效的(狀態)。如果可 能,選擇把0做為一個最好的默認。Planet枚舉類型沒有一個明確的默認值,無 論用戶是否任意的選擇一些行星,這都不會給人留下好的感覺。當你陷入這樣的 情況時,使用0做為一個非初始化的值,這也是在後面可以更新的:
public enum Planet
{
None = 0,
Mercury = 1,
Venus = 2,
Earth = 3,
Mars = 4,
Jupiter = 5,
Saturn = 6,
Neptune = 7,
Uranus = 8,
Pluto = 9
}
Planet sphere = new Planet ();
此時,sphere具有一個(默認)值None。為Planet枚舉類型添 加的這個非初始化的默認值,對ObservationData結構。最新創建的 ObservationData對象的目標上具有None和一個數值0。添加一個清晰的構造函數 讓用戶為你的類型的所有字段明白的初始化:
public struct ObservationData
{
Planet _whichPlanet; //what am I looking at?
Double _magnitude; // perceived brightness.
ObservationData( Planet target,
Double mag )
{
_whichPlanet = target;
_magnitude = mag;
}
}
但請記住,默認的構造函數還是可訪問的,而且是結構的部份。 用戶還是可以創建一個系統初始化的變量,而你無法阻止它。
在結束枚 舉類型轉而討論其它類型之前,你須要明白幾個用於標記的特殊枚舉類型規則。 枚舉類型在使用Flags特性時,必須把None的值設置為0:
[Flags]
public enum Styles
{
None = 0,
Flat = 1,
Sunken = 2,
Raised = 4,
}
很多開發 人員使用枚舉標記和位運算操作AND進行運行,0值會與位標記產生嚴重的問題。 下面這個實驗如果Flat的值是0時,是決不會成功的:
if ( ( flag & Styles.Flat ) != 0 ) // Never true if Flat == 0.
DoFlatThings( );
如果你遇到Flags,確保0對它來說是有效的, 並且這就著:“對所有缺少的標記。”
另一個很常見的初始 化問題就是值類型中包含了引用類型。字符串是一個常見的例子:
public struct LogMessage
{
private int _ErrLevel;
private string _msg;
}
LogMessage MyMessage = new LogMessage( );
MyMessage包含了一個_msg為 null的引用字段。這裡沒有辦法強行使用另一個不同的初始化方法,但你利用屬 性來局部化這個問題。你創建一個屬性向所用的用戶暴露_Msg的值。添加一個業 務邏輯,使得當字符串為null引用是,用空 串來取而代之:
public struct LogMessage
{
private int _ErrLevel;
private string _msg;
public string Message
{
get
{
return (_msg != null ) ?
_msg : string.Empty;
}
set
{
_msg = value;
}
}
}
(譯注: 我個人覺得這裡違反了原則一。當對兩個實例進行賦值COPY時,會出現,你明明 使用了a=b的運行,但實際上a!=b的結果。可以參見原則1。)
在你自己的 數據類型內部,你應該添加這樣的一個屬性。做了這樣的局部處理後,null引用 在某一位置做了驗證。當調用是在你的程序集內時,Message的訪問器基本上是 可以很好的內聯的。你將會取得高效低錯的代碼。
系統為所有的值類型 數據初始化為0,而沒有辦法防止用戶在創建一個值類型實例時,給所有的值類 型都賦值為0。如果可能,把0設置為自然的默認值。特殊情況下,使用Flags特 性的枚舉類型必須確保0是所有缺省標記的值。
返回教程目錄