備註
此內容經Pearson Education, Inc.授權從架構設計指導方針:可重複使用 .NET 程式庫的慣例、習慣用語與範式 (第2版)轉載。 該版於2008年出版,該書自那以後已於 第三版全面修訂。 此頁面的某些資訊可能已過期。
列舉是一種特殊的實值類型。 列舉有兩種:簡單列舉和旗標列舉。
簡單枚舉表示小型封閉的選擇集合。 常見的簡單列舉範例是色彩集。
旗標列舉的設計目的是支援列舉值的位運算。 旗標列舉的常見範例是選項清單。
✔️ DO 使用列舉來強類型化參數、屬性和傳回值,以表示值集。
✔️ DO 偏好使用列舉,而不是靜態常數。
❌ 請勿將列舉用於開放集合(例如作業系統版本、朋友的名稱等等)。
❌ 請勿提供預留的列舉值,供未來使用。
您始终可以在之后将值轻松添加到现有的枚举。 如需有關將值新增至列舉的詳細資訊,請參閱 將值新增至列舉。 保留值只會污染一組實際值,並傾向於導致用戶錯誤。
❌ 避免公開僅包含一個值的列舉型別。
確保 C API 未來擴充性的常見做法是將保留參數新增至方法簽章。 這類保留參數可以表示為具有單一預設值的列舉。 這不應該在受控 API 中完成。 方法多載允許在未來版本中新增參數。
❌ 請勿在列舉中包含監控值。
雖然哨兵值有時對框架開發人員很有幫助,但對於框架的使用者來說則容易感到困惑。 它們可用來追蹤列舉型別的狀態,而不是列舉型別所代表集合中的其中一個值。
✔️ DO 在簡單的列舉類型中設定值為零。
請考慮呼叫類似 「None」 的值。如果這類值不適用於這個特定的列舉,則列舉的最常見預設值應該指派為零的基礎值。
✔️ 請考慮使用 Int32 (大部分程式設計語言中的預設值) 作為列舉的基礎類型,除非下列任一項成立:
這個列舉類型是旗標列舉,您目前擁有超過 32 個旗標,或預期將來會有更多旗標。
基礎類型需要與 Int32 不同,以便更容易實現與預期不同大小枚舉的非受控代碼的互操作性。
較小的基礎類型會導致空間大幅節省。 如果您預期枚舉主要用作控制流程的參數,則其大小幾乎沒有影響。 尺寸節省可能相當顯著,如果:
您預期列舉會作為非常頻繁具現化的結構體或類別中的欄位使用。
您預期使用者會建立列舉實例的大型陣列或集合。
您預期列舉的實例數量龐大並將進行序列化。
針對記憶體內部使用量,請留意 Manage 物件始終與 DWORD 對齊,因此,為了優化記憶體使用,您實際上需要在實例中使用多個列舉或其他小型結構來封裝的方式才能讓較小的列舉發揮作用,因為實例大小總是會被調整至 DWORD。
✔️ 旗標列舉應該用複數名詞或名詞片語來命名,而簡單列舉應該用單數名詞或名詞片語來命名。
❌ 請勿直接擴充 System.Enum 。
System.Enum 是 CLR 用來建立使用者定義列舉的特殊類型。 大部分的程式設計語言都提供程式設計專案,可讓您存取這項功能。 例如,在 C# 中, enum 關鍵詞是用來定義列舉。
設計旗標列舉
✔️ 將 System.FlagsAttribute 套用至列舉型旗標。 請勿將此屬性套用至簡單枚舉。
✔️ 請對旗標列舉值使用兩個乘冪,以便使用位 OR 運算自由結合。
✔️ 請考慮為常用的旗標組合提供特殊列舉值。
位元運算這些是進階概念,對於簡單工作而言,不應該被要求所需要。 ReadWrite 是這類特殊值的範例。
❌ 避免創建旗標列舉,其中某些值的組合可能是無效的。
❌ 除非值代表「已清除所有旗標」並且按照下一個指導方針適當地命名,否則應避免使用代表零的旗標列舉值。
✔️ 請將旗標列舉的零值命名為None。 如果是旗標列舉,值必須一律表示「已清除所有旗標」。
將值新增至列舉
很常見的是,在您已經出貨後,發現需要將值新增到枚舉中。 從現有的 API 傳回新增值時,可能會發生應用程式相容性問題,因為撰寫不佳的應用程式可能無法正確處理新值。
✔️ 請考慮將值新增至列舉,儘管相容性風險很小。
如果您有因列舉類型的擴充而引起的應用程式不相容問題的實際數據,請考慮新增一個 API,讓其傳回新值和舊值,並讓舊的 API 廢棄,亦應保持只傳回舊值。 這可確保您現有的應用程式保持相容。
© 2005年、2009年Microsoft公司部分。 保留所有權利。
經 Pearson Education, Inc. 許可重新刊登自 Krzysztof Cwalina 和 Brad Abrams 所著的 架構設計指導方針: 可重複使用的 .NET 程式庫慣例、慣用語和模式,第 2 版,2008 年 10 月 22 日由 Addison-Wesley Professional 發行,作為 Microsoft Windows 開發系列的一部分。