.NET程式在物件初始時,變數初始器會將成員變數做初始化的動作。對於值類型的成員變數來說,會被初始為0值。因此我們應將0視為值類型的默認值。

以列舉型別來看,假設今天我有一個列舉型別:

enum Sex
{
    Boy=1,
    Girl=2
}

其列舉值並未從0,而是從1開始。則初始值0對該列舉來說,是一個無效的狀態。程式也可能因此無法正常運作。像是:

class Program
{
    static void Main(string[] args)
    {
        Person p=new Person();
        //p.Sex = Sex.Boy;
        Console.WriteLine(p.Sex.ToString ());        
    }
}
enum Sex
{
    Boy = 1,
    Girl = 2
}
struct Person
{
    public String Name;
    public Sex Sex ;
}

運行結果如下:

但在正常的情況下,列舉值應該要在列舉範圍內,運行結果應顯示如下這般:

這樣的問題我們無法透過建構子給予初始值來解決,因為就算指定了具備參數的建構子。

struct Person
{
    public String Name;
    public Sex Sex ;
    public Person(String name,Sex sex)
    {
        this.Name = name;
        this.Sex = sex;
    }
}

對於值類型來說仍有預設建構子可以使用。像是:

class Program
{
    static void Main(string[] args)
    {
        Person p=new Person();
        Console.WriteLine(p.Sex.ToString ());        
    }
}
enum Sex
{
    Boy = 1,
    Girl = 2
}

struct Person
{
    public String Name;
    public Sex Sex;

    public Person(String name, Sex sex)
    {
        this.Name = name;
        this.Sex = sex;
    }
}

且值類型的預設建構子無法自行撰寫,若嘗試撰寫編譯器會發出"Structs cannot contain explicit parameterless constructors"的錯誤。

而若想透過變數初始器來做設定的動作,編譯器也會以"cannot have instance field initializers"錯誤告知。

因此我們在使用值類型時特別留意其初始值,確保0為值類型的有效狀態,避免上述問題的發生。就像這樣:

class Program
{
    static void Main(string[] args)
    {
        Person p=new Person();
        Console.WriteLine(p.Sex.ToString ());        
    }
}
enum Sex
{
    NotSet = 0,
    Boy = 1,
    Girl = 2
}

struct Person
{
    public String Name;
    public Sex Sex;

    public Person(String name, Sex sex)
    {
        this.Name = name;
        this.Sex = sex;
    }
}

除此之外,當撰寫設有Flags屬性的列舉型別,我們也要特別留意。除必須確保初始值0為有效狀態外,還需讓其值為沒有設定任何標記的狀態。像是:

[Flags]

public enum Styles { None=0, Flat=1. Sunken=2, Raised=4 }

這是因為設有Flags屬性的列舉型態,我們可能會拿來做像下面這樣的運算:

if((flag & Styles.Flat) != 0)
DoFlatThings();

當Flat是0的話,判斷式依舊為false,達不到預期的效果。不過,這例子只是告知建議遵守該條款的原因。事實上,這樣的問題可以像下面這樣避開:

if((flag & Styles.Flat) == Styles.Flat)
DoFlatThings();