default 是在 C# 中,用以取得指定型別 (type) 的「預設值」的關鍵字,簡單的範例用法如下︰

default(型別);

從 MSDN 上關於 default keyword 的說明頁面中,整理「預設值」的回傳規則如下︰

  • 如果指定的型別是 Reference type 的話,則 default 關鍵字回傳值是 null
  • 如果指定的型別是數值類型 (numeric) Value type 的話,則 default 關鍵字回傳值是 0
  • 如果指定的型別是可為 null (nullable) Value types 的話,則 default 關鍵字回傳值是 System.Nullable<T>
  • 如果指定的型別是 struct 的話,則 default 關鍵字回傳值是一個新的 struct object,但 struct object 中的每個成員的值,內容一樣會遵照上述三個規定做設定

但上述的描述中,我們看到,MSDN 中沒有針對像 DateTime、列舉等型別的預設值做出說明,所以我撰寫了簡單的測試程式,來做這部份預設值的實驗。

為了測試方便,所以我定義了一個類別、一個結構與兩個列舉型別 (一個有針對成員設定值,另一個則沒有),以方便測試,型別定義整理如下︰

類別︰DemoClass

/// 
/// 測試用類別
/// 
public class DemoClass
{
    /// 
    /// Value Type 屬性
    /// 
    public int ValueTypeProperty { get; set; }

    /// 
    /// Reference Type 屬性
    /// 
    public List ReferenceTypeProperty { get; set; }
}

結構︰DemoStruct

/// 
/// 測試用結構
/// 
public struct DemoStruct
{
    /// 
    /// Value Type 屬性
    /// 
    public int ValueTypeProperty { get; set; }

    /// 
    /// Reference Type 屬性
    /// 
    public List ReferenceTypeProperty { get; set; }
}

列舉︰DemoEnum (指定每個列舉值,背後代表一個整數)

/// 
/// 測試用列舉 (指定每個列舉值,背後代表一個整數)
/// 
public enum DemoEnum : int 
{
    Value1 = 1,
    Value2 = 2
}

列舉︰DemoEnumWithoutValue (不指定每個列舉值,背後代表一個整數)

/// 
/// 測試用列舉 (不指定每個列舉值,背後代表一個整數)
/// 
public enum DemoEnumWithoutValue : int
{
    Value1,
    Value2
}

針對各型別的 default keyword 回傳值,我整理如下表︰

型別 default 回傳值 說明
List null Reference Type 回傳 null
string null
int 0 數值型的 Value Type 回傳 0
int? null 回傳 System.Nullable<int>
DateTime 0001/1/1 上午 12:00:00 即為 DateTime.MinValue
DateTime? null 回傳 System.Nullable<DateTime>
DamoClass null
DamoStruct ValueTypeProperty = 0
ReferenceTypeProperty = null
結構的每個成員,其值設定為 default 關鍵字回傳的預設值
DemoEnum 0 列舉成員值有設定數值,則回傳 0 
DemoEnumWithoutValue Value1 列舉成員值沒有設定數值,則回傳此列舉的第一個成員 (其值為 0)

補充說明︰

1. 針對 DateTime 型別,首先要先注意的是,DateTime 型別是 struct,所以是 Value Type 而不是 Reference type

而 DateTime 內部的結構,其實是記錄一個 ulong 型別的 ticks (千萬分之一秒) 屬性值。當我們對 DateTime 型別做操作或是取得日期資訊 (ex: 年、月) 時,背後其實是使用 ticks 屬性值來做相關的計算。

因此所謂的 DateTime.MinValue,其實就是 ticks 屬性為 0 的 DateTime object,而 .Net Framework 定義 ticks 屬性值為 0 的起始點為︰0001 年 1 月 1 日午夜 12:00:00。

而 DateTime 型別因為是 struct,因此 default(DateTime) 會回傳一個 DateTime object,其中的 ticks 屬性因為是 long 型別,所以預設值為 0。因此 default(DateTime) 的值會與 DateTime.MinValue 值相等 (因此兩者內部的 ticks 皆為 0)。

2. 另外在這邊要注意,在列舉型別中,如果沒有特別針對成員設定值的話 (像 DemoEnum),其成員的值是從 0 開始編號。因此 DemoEnumWithoutValue.Value1,背後的值其實是 0,所以 default(DemoEnumWithoutValue) 會顯示 Value1,其實是合理且一致的。

測試程式︰

測試程式我已經上傳到 GitHub,網址如下︰https://gist.github.com/LittleLin/5390639,可以使用 SnippetCompiler 來運行上面的測試程式碼,或是開 Visual Studio 執行也可以。

References: