Designing Flags Enumerations

Flags enumerations are used for masking bit fields and doing bitwise comparisons. They are the correct design to use when multiple enumeration values can be specified at the same time. For example, you can combine any of the GenericUriParserOptions enumeration values to configure a generic Uniform Resource Identifier (URI) parser.

Do apply the System.FlagsAttribute to flags enumerations. Do not apply this attribute to simple enumerations.

Do use powers of two for a flags enumeration's values so they can be freely combined using the bitwise OR operation.

Important noteImportant

If you do not use powers of two or combinations of powers of two, bitwise operations will not work as expected.

Consider providing special enumeration values for commonly used combinations of flags.

Combining flags enumeration values is an intermediate skill that should not be required for developers implementing common scenarios. For example, the FileShare enumeration contains the ReadWrite value to specify that a shared file can be opened for reading or writing. This shows developers that they can open a shared file for reading or writing, and eliminates the need for them to learn how to specify a combination of enumeration values as a single value.

Avoid creating flags enumerations when certain combinations of values are invalid.

This problem typically indicates that the meaning of the enumeration is not sufficiently precise. Consider dividing the enumeration into two or more enumerations, each having a more precise set of values. For example, consider the following poorly defined enumeration.

<Flags()> _
Public Enum PurchaseTypes

    SalePrice
    RegularPrice
    Book
    CompactDisk

End Enum

[Flags]
public enum PurchaseTypes
{
    SalePrice,
    RegularPrice,
    Book,
    CompactDisk
}

The designer intends this enumeration to be used with the following method.

Public Overloads Function FindPriceForItem(ByVal title As String, ByVal purchase As PurchaseTypes) As Single
    Return 0
End Function
public float FindPriceForItem(string title, PurchaseTypes purchase)

When calling this method, the purchase parameter specifies exactly one of the SalePrice or RegularPrice values and exactly one of the Book or CompactDisk values. Developers would not be able to determine this requirement without consulting the documentation or experimenting with the method. A better approach is to separate the two kinds of information, placing each in its own enumeration, as shown in the following code example.

Public Enum ItemType

    Book
    CompactDisk

End Enum

Public Enum PriceType

    SalePrice
    RegularPrice

End Enum

public enum ItemType
{
    Book,
    CompactDisk
}

public enum PriceType
{
    SalePrice,
    RegularPrice,
}

The method signature would now change to reflect this redesign, as shown in the following code example.

Public Overloads Function FindPriceForItem(ByVal title As String, ByVal name As ItemType, ByVal price As PriceType) As Single
    Return 0
End Function
public float FindPriceForItem(string title, ItemType name, PriceType price)

Avoid setting a flags enumeration value to zero, unless the value is used to indicate that all flags are cleared. Such a value should be named appropriately as described in the next guideline.

Note that this guideline is only for flags enumerations. Simple enumerations can and should use the zero value.

Do name the zero value of flags enumerations None. For a flags enumeration, the value must always mean all flags are cleared.

Important noteImportant

Do not use the value zero in a flags enumeration to indicate any other state. There is no way to check for a zero value flag being explicitly set, as opposed to no flags being set.

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

Enumeration Design

Adding Values to Enumerations

Other Resources

Type Design Guidelines

Design Guidelines for Developing Class Libraries