枚举设计

注意

此内容根据 Pearson Education, Inc. 许可转载自《框架设计指南:可重用 .NET 库的约定、习语和模式第二版》。 该版本于 2008 年出版,并在此后于第三版对该书进行了全面修订。 此页上的一些信息可能已过时。

枚举是一种特殊的值类型。 枚举分为两种:简单枚举和标志枚举。

简单枚举表示封闭的小型选项集。 简单枚举的一个常见示例是颜色集。

标志枚举旨在支持对枚举值执行位运算。 标志枚举的一个常见示例是选项列表。

✔️ 务必使用枚举对表示值集的参数、属性和返回值进行强类型化。

✔️ 支持使用枚举而不是静态常量。

❌ 不要将枚举用于开放集(例如操作系统版本、朋友的姓名等)。

❌ 不要提供保留的枚举值以供将来使用。

在后续阶段,始终可以直接向现有枚举添加值。 有关向枚举添加值的更多详细信息,请参阅向枚举添加值。 保留值只会污染真实值集,容易导致用户错误。

❌ 避免公开只有一个值的枚举。

确保 C API 未来扩展性的常见做法是将保留参数添加到方法签名。 此类保留参数可以表示为具有单个默认值的枚举。 不应在托管 API 中完成此操作。 方法重载允许在未来版本中添加参数。

❌ 不要在枚举中包含 sentinel 值。

尽管 sentinel 值有时对框架开发人员很有帮助,但也会让框架用户感到困惑。 它们用于跟踪枚举的状态,而不是作为枚举所表示的集中的值之一。

✔️ 务必在简单枚举中提供零值。

考虑将该值命名为“None”。如果此类值不适用于此特定枚举,则应为枚举最常见的默认值分配基础值“零”。

✔️ 除非满足以下任一条件,否则考虑使用 Int32(大多数编程语言中的默认值)作为枚举的基础类型:

  • 枚举是标志枚举,并且你有超过 32 个标志,或者预计将来会有更多。

  • 为了简化与需要不同大小枚举的非托管代码的互操作,基础类型不能是 Int32

  • 较小的基础类型会显著节省空间。 如果希望枚举主要用作控制流的参数,那么大小无关紧要。 在以下情况下,大小节省可能会很显著:

    • 你希望将枚举用作非常频繁实例化的结构或类中的字段。

    • 你希望用户创建枚举实例的大型数组或集合。

    • 你希望序列化大量枚举实例。

在内存中使用时,请注意托管对象始终为 DWORD 对齐,因此,实际上需要在一个实例中使用多个枚举或其他小型结构来打包一个较小的枚举,以便产生影响,因为总实例大小始终会四舍五入到 DWORD

✔️ 务必用复数名词或名词短语为标志枚举命名,用单数名词或名词短语为简单枚举命名。

❌ 请勿直接扩展 System.Enum

System.Enum 是 CLR 用来创建用户定义枚举的特殊类型。 大多数编程语言都提供了一个编程元素,可让你访问此功能。 例如,在 C# 中,enum 关键字用于定义枚举。

设计标志枚举

✔️ 务必将 System.FlagsAttribute 应用于标志枚举。 不要将此属性应用于简单枚举。

✔️ 务必对标志枚举值使用 2 的幂,以便使用按位 OR 运算自由组合这些值。

✔️ 考虑为常用的标志组合提供特殊的枚举值。

位运算是一个高级概念,简单任务不需要。 ReadWrite 就是此类特殊值的一个示例。

❌ 避免在某些值组合无效的情况下创建标志枚举。

❌ 避免使用标志枚举值“零”,除非该值表示“所有标志均已清除”并且按下一个准则所述正确命名。

✔️ 务必将标志枚举的零值命名为 None。 对于标志枚举,该值必须始终表示“所有标志均已清除”。

向枚举添加值

交付枚举后,发现需要向其添加值,这种情况很常见。 从现有 API 返回新添加的值时,存在潜在的应用程序兼容性问题,因为编写不当的应用程序可能无法正确处理新值。

✔️ 尽管存在较小的兼容性风险,仍考虑向枚举添加值。

如果有真实数据证明,向枚举添加值会导致应用程序不兼容,请考虑添加一个返回新值和旧值的新 API,并弃用继续只返回旧值的旧 API。 这将确保现有应用程序保持兼容。

Portions © 2005, 2009 Microsoft Corporation 版权所有。 保留所有权利。

在 Pearson Education, Inc. 授权下,由 Addison-Wesley Professional 作为 Microsoft Windows 开发系列的一部分再版自 Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries, 2nd Edition(Framework 设计准则:可重用 .NET 库的约定、惯例和模式第 2 版),由 Krzysztof Cwalina 和 Brad Abrams 发布于 2008 年 10 月 22 日。

请参阅