注释
此内容由 Pearson Education, Inc. 的许可从 框架设计指南:可重用 .NET 库的约定、习惯和模式(第 2 版)重新打印。 该版于2008年出版,此后该书已于 第三版全面修订。 此页上的一些信息可能已过期。
枚举是一种特殊的值类型。 有两种类型的枚举:简单枚举和标志枚举。
简单枚举表示小型封闭式选项集。 简单枚举的常见示例是一组颜色。
标志枚举旨在支持对枚举值执行位运算。 标志枚举的一个常见示例是选项列表。
✔️ 务必使用枚举对表示值集的参数、属性和返回值进行强类型化。
✔️ 请优先使用枚举而不是静态常量。
❌ 请勿对开放集合使用枚举(例如操作系统版本、好友的姓名等)。
❌ 请勿提供用于将来使用的保留枚举值。
在后续阶段,始终可以直接向现有枚举添加值。 有关将 值 添加到枚举的更多详细信息,请参阅向枚举添加值。 保留值只会污染一组实际值,并往往导致用户错误。
❌ 避免公开只有一个值的枚举。
确保 C API 的未来可扩展性的常见做法是向方法签名添加保留参数。 此类保留参数可以表示为具有单个默认值的枚举。 不应在托管 API 中执行此作。 方法重载允许在将来的版本中添加参数。
❌ 请勿在枚举中包含标识符值。
虽然它们有时对框架开发人员有帮助,但哨兵值会让框架的用户感到困惑。 它们用于跟踪枚举的状态,而不是作为枚举所表示的集中的值之一。
✔️ 请为简单枚举提供一个零值。
请考虑调用类似于“None”的值。如果此类值不适合此特定枚举,则应为枚举分配基础值 0 的最常见默认值。
✔️ 请考虑使用 Int32 (大多数编程语言中的默认值)作为枚举的基础类型,除非存在以下任一情况:
枚举是标志枚举,并且你有超过 32 个标志,或者预计将来会有更多。
为了简化与需要不同大小枚举的非托管代码的互操作,基础类型不能是 Int32。
较小的基础类型将导致空间大幅节省。 如果你预期枚举主要用作控制流程的参数,那么大小就没有太大影响。 出现以下情况时,尺寸节省会非常显著:
你希望将枚举用作非常频繁实例化的结构或类中的字段。
你期望用户创建大型数组或枚举实例的集合。
你希望序列化大量枚举实例。
在内存中使用时,请注意托管对象始终为 DWORD
对齐,因此,实际上需要在一个实例中使用多个枚举或其他小型结构来打包一个较小的枚举,以便产生影响,因为总实例大小始终会四舍五入到 DWORD
。
✔️ 务必用复数名词或名词短语为标志枚举命名,用单数名词或名词短语为简单枚举命名。
❌ 请勿直接扩展 System.Enum 。
System.Enum 是 CLR 用于创建用户定义的枚举的特殊类型。 大多数编程语言都提供一个编程元素,可让你访问此功能。 例如,在 C# 中,关键字 enum
用于定义枚举。
设计标志枚举
✔️ 务必将 System.FlagsAttribute 应用于标志枚举。 不要将此属性应用于简单枚举。
✔️ 务必对标志枚举值使用 2 的幂,以便使用按位 OR 运算自由组合这些值。
✔️ 请考虑为常用标志组合提供特殊枚举值。
按位运算是一个高级概念,对于简单任务,不应该要求这样做。 ReadWrite 是此类特殊值的示例。
❌ 避免在某些值组合无效的情况下创建标志枚举。
❌ 避免使用标志枚举值“零”,除非该值表示“所有标志均已清除”并且按下一个准则所述正确命名。
✔️ 务必将标志枚举的零值命名为 None
。 对于标志枚举,该值必须始终表示“所有标志均已清除”。
向枚举添加值
交付枚举后,发现需要向其添加值,这种情况很常见。 从现有 API 返回新添加的值时,可能存在应用程序兼容性问题,因为编写不当的应用程序可能无法正确处理新值。
✔️ 考虑向枚举添加值,尽管兼容性风险很小。
如果您有关于添加枚举值导致应用程序不兼容的实际数据,请考虑添加一个新的 API 来返回新旧值,并弃用旧的 API,旧的 API 应继续仅返回旧值。 这将确保现有应用程序保持兼容。
部分内容 © 2005, 2009 Microsoft 公司。 保留所有权利。
获得皮尔逊教育公司许可后重印自 框架设计准则:可重用 .NET 库的约定、习惯和模式 ,由 Krzysztof Cwalina 和 Brad Abrams 编写,并作为微软 Windows 开发系列中的出版物之一,于 2008 年 10 月 22 日由 Addison-Wesley Professional 出版。