Recipe 4.6 Determining Whether One or More Enumeration Flags Are Set

Problem

You need to determine whether a variable of an enumeration type, consisting of bit flags, contains one or more specific flags. For example, given the following enumeration Language :

 [Flags] enum Language {     CSharp = 0x0001, VBNET = 0x0002, VB6 = 0x0004, Cpp = 0x0008 } 

Determine, using Boolean logic, whether the variable lang in the following line of code contains a language such as Language.CSharp and/or Language.Cpp :

 Language lang = Language.CSharp  Language.VBNET; 

Solution

To determine whether a variable contains a single bit flag that is set, use the following conditional:

 if((lang & Language.CSharp) == Language.CSharp) {     // lang contains at least Language.CSharp } 

To determine whether a variable exclusively contains a single bit flag that is set, use the following conditional:

 if(lang == Language.CSharp) {     // lang contains only the Language.CSharp } 

To determine whether a variable contains a set of bit flags that are all set, use the following conditional:

 if((lang & (Language.CSharp  Language.VBNET)) ==     (Language.CSharp  Language.VBNET)) {     // lang contains at least Language.CSharp and Language.VBNET } 

To determine whether a variable exclusively contains a set of bit flags that are all set, use the following conditional:

 if((lang  (Language.CSharp  Language.VBNET)) ==     (Language.CSharp  Language.VBNET)) {     // lang contains only the Language.CSharp and Language.VBNET } 

Discussion

When enumerations are used as bit flags (these enumerations should be marked with the Flags attribute) they usually will require some kind of conditional testing to be performed. This kind of conditional testing requires the use of the bitwise AND ( & ) and OR ( ) operators.

Testing for a variable having a specific bit flag set is done with the following conditional statement:

 if((lang & Language.CSharp) == Language.CSharp) 

where lang is of the Language enumeration type.

The & operator is used with a bitmask to determine whether a bit is set to 1 . The result of AND ing two bits is 1 only when both bits are 1 ; otherwise , the result is . We can use this operation to determine if a specific bit flag is set to a 1 in the number containing the individual bit flags. If we AND the variable lang with the specific bit flag we are testing for (in this case Language.CSharp ), we can extract that single specific bit flag. The expression (lang & Language.CSharp) is solved in the following manner if lang is equal to Language.CSharp :

 Language.CSharp      0001 lang  0001  ANDed bit values     0001 

If lang is equal to another value such as Language.VBNET , the expression is solved in the following manner:

 Language.CSharp      0001 lang  0010  ANDed bit values     0000 

Notice that AND ing the bits together returns the value Language.CSharp in the first expression and 0x0000 in the second expression. Comparing this result to the value we are looking for ( Language.CSharp ) tells us whether that specific bit was turned on.

This method is great for checking specific bits, but what if you wanted to know if only a specific bit was turned on (and all other bits turned off) or off (and all other bits turned on)? To test whether only the Language.CSharp bit is turned on in the variable lang , we can use the following conditional statement:

 if(lang == Language.CSharp) 

Consider the situation if the variable lang contained only the value Language.CSharp . The expression using the OR operator would look like this:

 Language.CSharp      0001 lang  0001  ORed bit values      0001 

Now, add a language value or two to the variable lang and perform the same operation on lang :

 Language.CSharp      0001 lang  1101  ORed bit values      1101 

The first expression results in the same value as we are testing against. The second expression results in a much larger value than Language.CSharp . This result indicates that the variable lang in the first expression only contains the value Language.CSharp and the second expression contains other languages including Language.CSharp .

Using this same formula, we can test multiple bits to determine whether they are both on and all other bits are off. This is done in the following conditional statement:

 if((lang & (Language.CSharp  Language.VBNET)) ==     (Language.CSharp  Language.VBNET)) 

Notice that to test for more than one language, we simply OR the language values together. By switching the first & operator for an operator, we can determine whether at least these bits are turned on. This is done in the following conditional statement:

 if((lang  (Language.CSharp  Language.VBNET)) ==     (Language.CSharp  Language.VBNET)) 

When testing for multiple enumeration values, it may be beneficial to add a value to your enumeration, which OR s together all the values you want to test for. If we wanted to test for all languages except Language.CSharp , our conditional statement(s) would grow quite large and unwieldy. To fix this, we could add a value to the Language enumeration that OR s together all languages except Language.CSharp . The new enumeration would look like this:

 [Flags] enum Language {     CSharp = 0x0001, VBNET = 0x0002, VB6 = 0x0004, Cpp = 0x0008,     AllLanguagesExceptCSharp = VBNET  VB6  Cpp } 

and our conditional statement might look similar to the following:

 if((lang  Language.AllLanguagesExceptCSharp) ==     Language. AllLanguagesExceptCSharp) 

This statement is quite a bit smaller and is easier to manage and read.

Use the AND operator when testing whether one or more bits are set to 1 . Use the OR operator when testing whether one or more bits are set to .




C# Cookbook
C# 3.0 Cookbook
ISBN: 059651610X
EAN: 2147483647
Year: 2003
Pages: 315

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net