iT邦幫忙

DAY 8
1

.NET程式效能Issue系列 第 8

[Day 8][C#]Effective C# 條款八: 確保0為值類型的有效狀態

  • 分享至 

  • twitterImage
  •  

.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();  

上一篇
[Day 7][C#]Effective C# 條款七: 將值類型盡可能實現為具有常量性與原子性的類型
下一篇
[Day 9][C#]Effective C# 條款九: 理解幾個相等判斷之間的關係
系列文
.NET程式效能Issue11
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言