FlagsAttribute Class
Indicates that an enumeration can be treated as a bit field; that is, a set of flags.
Assembly: mscorlib (in mscorlib.dll)
Bit fields are generally used for lists of elements that might occur in combination, whereas enumeration constants are generally used for lists of mutually exclusive elements. Therefore, bit fields are designed to be combined with a bitwise OR operation to generate unnamed values, whereas enumerated constants are not. Languages vary in their use of bit fields compared to enumeration constants.
Attributes of the FlagsAttribute
AttributeUsageAttribute is applied to this class, and its Inherited property specifies false. This attribute can only be applied to enumerations.
Guidelines for FlagsAttribute and Enum
-
Use the FlagsAttribute custom attribute for an enumeration only if a bitwise operation (AND, OR, EXCLUSIVE OR) is to be performed on a numeric value.
-
Define enumeration constants in powers of two, that is, 1, 2, 4, 8, and so on. This means the individual flags in combined enumeration constants do not overlap.
-
Consider creating an enumerated constant for commonly used flag combinations. For example, if you have an enumeration used for file I/O operations that contains the enumerated constants Read = 1 and Write = 2, consider creating the enumerated constant ReadWrite = Read OR Write, which combines the Read and Write flags. In addition, the bitwise OR operation used to combine the flags might be considered an advanced concept in some circumstances that should not be required for simple tasks.
-
Use caution if you define a negative number as a flag enumerated constant because many flag positions might be set to 1, which might make your code confusing and encourage coding errors.
-
A convenient way to test whether a flag is set in a numeric value is to perform a bitwise AND operation between the numeric value and the flag enumerated constant, which sets all bits in the numeric value to zero that do not correspond to the flag, then test whether the result of that operation is equal to the flag enumerated constant.
-
Use None as the name of the flag enumerated constant whose value is zero. You cannot use the None enumerated constant in a bitwise AND operation to test for a flag because the result is always zero. However, you can perform a logical, not a bitwise, comparison between the numeric value and the None enumerated constant to determine whether any bits in the numeric value are set.
If you create a value enumeration instead of a flags enumeration, it is still worthwhile to create a None enumerated constant. The reason is that by default the memory used for the enumeration is initialized to zero by the common language runtime. Consequently, if you do not define a constant whose value is zero, the enumeration will contain an illegal value when it is created.
If there is an obvious default case your application needs to represent, consider using an enumerated constant whose value is zero to represent the default. If there is no default case, consider using an enumerated constant whose value is zero that means the case that is not represented by any of the other enumerated constants.
-
Do not define an enumeration value solely to mirror the state of the enumeration itself. For example, do not define an enumerated constant that merely marks the end of the enumeration. If you need to determine the last value of the enumeration, check for that value explicitly. In addition, you can perform a range check for the first and last enumerated constant if all values within the range are valid.
-
Do not specify enumerated constants that are reserved for future use.
-
When you define a method or property that takes an enumerated constant as a value, consider validating the value. The reason is that you can cast a numeric value to the enumeration type even if that numeric value is not defined in the enumeration.
The following code example illustrates the use of the FlagsAttribute attribute and shows the effect on the ToString method of using FlagsAttribute on an Enum declaration.
// Example of the FlagsAttribute attribute. using System; class FlagsAttributeDemo { // Define an Enum without FlagsAttribute. enum SingleHue : short { Black = 0, Red = 1, Green = 2, Blue = 4 }; // Define an Enum with FlagsAttribute. [FlagsAttribute] enum MultiHue : short { Black = 0, Red = 1, Green = 2, Blue = 4 }; static void Main( ) { Console.WriteLine( "This example of the FlagsAttribute attribute \n" + "generates the following output." ); Console.WriteLine( "\nAll possible combinations of values of an \n" + "Enum without FlagsAttribute:\n" ); // Display all possible combinations of values. for( int val = 0; val <= 8; val++ ) Console.WriteLine( "{0,3} - {1}", val, ( (SingleHue)val ).ToString( ) ); Console.WriteLine( "\nAll possible combinations of values of an \n" + "Enum with FlagsAttribute:\n" ); // Display all possible combinations of values. // Also display an invalid value. for( int val = 0; val <= 8; val++ ) Console.WriteLine( "{0,3} - {1}", val, ( (MultiHue)val ).ToString( ) ); } } /* This example of the FlagsAttribute attribute generates the following output. All possible combinations of values of an Enum without FlagsAttribute: 0 - Black 1 - Red 2 - Green 3 - 3 4 - Blue 5 - 5 6 - 6 7 - 7 8 - 8 All possible combinations of values of an Enum with FlagsAttribute: 0 - Black 1 - Red 2 - Green 3 - Red, Green 4 - Blue 5 - Red, Blue 6 - Green, Blue 7 - Red, Green, Blue 8 - 8 */
Windows 7, Windows Vista, Windows XP SP2, Windows XP Media Center Edition, Windows XP Professional x64 Edition, Windows XP Starter Edition, Windows Server 2008 R2, Windows Server 2008, Windows Server 2003, Windows Server 2000 SP4, Windows Millennium Edition, Windows 98, Windows CE, Windows Mobile for Smartphone, Windows Mobile for Pocket PC, Xbox 360, Zune
The .NET Framework and .NET Compact Framework do not support all versions of every platform. For a list of the supported versions, see .NET Framework System Requirements.
[Flags]
public enum MyFlagEnum
{
FirstFlag = 1,
SecondFlag = 2,
ThirdFlag = 4,
FourthFlag = 8,
}
You would check to see if a flag is set for a given value like this:
MyFlagEnum flagValue = DetermineFlagValue(); // returns some enumerate value you want to check
if((flagValue & MyFlagEnum.SecondFlag) == MyFlagEnum.SecondFlag)
{
// SecondFlag was set, so handle it
}
This code gets very busy, especially if you have a particularly long name for either the enumeration or its flags (or both!). Fortunately, there is a very simple extension method you can build for your enumerations that will make your code look a lot cleaner:
public static class MyFlagEnumHelper
{
public static bool HasFlag(this MyFlagEnum item, MyFlagEnum query)
{
return ((item & query) == query);
}
}
Then, when you want to check if a flag is set:
MyFlagEnum flagValue = DetermineFlagValue(); // returns some enumerate value you want to check
if(flagValue.HasFlag(MyFlagEnum.SecondFlag))
{
// SecondFlag was set, so handle it
}
Cleaner and easier to understand. Unfortunately the compiler tricks used to create enums mean there's no generic extension method that can be used for all enumerations; you're going to have to include a separate extension method for each flag enumeration you create. Still, that's what snippets are for, right? :)
------
Not sure what the protocol is on MSDN for responding to a post, so I'm just editing in my response. You don't need the "== value" portion, the "a & b" will return 0 or non-zero, meaning you can use it as a simple conditional. Or if you're really picky, you can use "!= 0" or "> 0" to indicate a "true" result. This way you can also check for multiple settings in the same conditional test. All of this is pretty standard bitmask interaction going back decades. For example:
MyFlagEnum flagValue = DetermineFlagValue();
if((flagValue & MyFlagEnum.SecondFlag) > 0)
{
// SecondFlag was set, so handle it
}
- 6/25/2008
- RandolphoAtKroll
- 10/3/2009
- m_v10
The maximum Int32 value is 2147483647 and is easily mistaken as the highest flag value. In fact it has all bits set which is useful as an enum flag value for testing for all.
The SQL datatype should be [int].
- 1/22/2009
- LukePuplett
- 1/22/2009
- LukePuplett
Some of us have trouble remembering the powers of two all the way up the scale, however, so if you don't want to have to calculate them or are afraid you might miss one, here's another way to build your flags: use the bitshift operator to define your flag values. Recall (or learn) that:
1 << 0 = 1 (decimal) = 00000001 (binary)
1 << 1 = 2 (decimal) = 00000010 (binary)
1 << 2 = 4 (decimal) = 00000100 (binary)
1 << 3 = 8 (decimal) = 00001000 (binary)
See the pattern there? All you have to do is build your enum to use increasing bitshifts of 1 like this (C# example):
[Flags]Guaranteed bitwise compatible flags without having to memorize or calculate the powers of two.
public enum MyEnum
{
Default = 0,
Val1 = 1 << 0,
Val2 = 1 << 1,
Val4 = 1 << 2,
Val8 = 1 << 3,
Val2OrVal4 = Val2 | Val4
}
- 6/25/2008
- RandolphoAtKroll
- 6/25/2008
- RandolphoAtKroll
Enum positions for 0 and 1 should toggle themselves. If the enumeration is not 0 then it must be 1 and vice-versa. It does not necessarily have to mean that 0 would stand for ‘no value’, just that 1 must be a setting that will never interfere with zero. Furthermore, I do agree with your post as black and red are not exactly exclusive to each other (perhaps the color can be black or red but not both at the same time for whatever Microsoft is doing, LOL!!!).
- http://www.syadmins.com
- 6/8/2008
- www.syadmins.com
I don't think you should use 0 for enums meant for bitwise operation. 0 means 'no value' as shown in the example above. Because the sample starts at two, you don't actually get all of the possible color combinations. The sample should be updated for the enum value to start at 1, and increment by powers of 2 (up to 16).
- 2/5/2008
- noeleee