Enumeration Design 

Enumerations provide sets of constant values that are useful for strongly typing members and improving readability of code. Enumerations are either simple or flags. Simple enumerations contain values that are not combined or used in bitwise comparisons. Flags enumerations are intended to be combined using bitwise OR operations. Combinations of flags enumeration values are examined using bitwise AND operations.

The following guidelines describe the best practices for enumeration design.

Do use an enumeration to strongly type parameters, properties, and return values that represent sets of values.

Do favor using an enumeration instead of static constants.

The following code example demonstrates the incorrect design.

public static class BadFurnishings
{
    public static int Table = 1;
    public static int Chair = 2;
    public static int Lamp = 3;
}

The following code example demonstrates the enumeration that should be used in place of the static constants.

public enum GoodFurnishings
{
    Table,
    Chair,
    Lamp
}

Do not use an enumeration for open sets such as the operating system version.

Adding values to an enumeration that has already shipped can break existing code. There are times when this is acceptable, but you should not design an enumeration where this is likely to be the case.

Do not define reserved enumeration values that are intended for future use.

In some situations you might decide that adding values to the shipped enumeration is worth the risk of possibly breaking existing code. You can also define a new enumeration and members that work with its values.

Avoid publicly exposing enumerations with only one value.

Do not include sentinel values in enumerations.

Sentinel values are used to identify the boundaries of values in the enumeration. Typically a sentinel value is used in range checks and is not a valid data value. The following code example defines an enumeration with a sentinel value.

public enum Furniture
{
    Desk,
    Chair,
    Lamp,
    Rug,
    LastValue   // The sentinel value.
}

Do provide a value of zero on simple enumerations.

If possible, name this value None. If None is not appropriate, assign the value zero to the most commonly used value (the default).

Consider using System.Int32 (the default data type in most programming languages) as the underlying data type of an enumeration unless any of the following is true:

  • The enumeration is a flags enumeration, and you have more than 32 flags or expect to have more in the future.

  • The underlying type needs to be different than Int32 for easier interoperability with unmanaged code expecting different size enumerations.

  • A smaller underlying type would result in substantial savings in space. If you expect an enumeration to be used mainly as an argument for flow of control, the size makes little difference. The size savings might be significant if:

    • You expect the enumeration to be used as a field in a very frequently instantiated structure or class.

    • You expect users to create large arrays or collections of enumeration instances.

    • You expect a large number of instances of the enumeration to be serialized.

Do name flags enumerations with plural nouns or noun phrases. Simple enumerations should be named with singular nouns or noun phrases.

Do not extend System.Enum directly.

Some compilers do not allow you to extend Enum unless you do it indirectly using the language-specific key word for generating enumerations.

Portions Copyright 2005 Microsoft Corporation. All rights reserved.

Portions Copyright Addison-Wesley Corporation. All rights reserved.

For more information on design guidelines, see the "Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries" book by Krzysztof Cwalina and Brad Abrams, published by Addison-Wesley, 2005.

See Also

Concepts

Designing Flags Enumerations
Adding Values to Enumerations

Other Resources

Type Design Guidelines
Design Guidelines for Developing Class Libraries