Recipe1.21.Determining if One or More Enumeration Flags Are Set


Recipe 1.21. Determining if One or More Enumeration Flags Are Set

Problem

You need to determine if 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, if 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 if 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 if 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 if 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 if 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 and are marked with the Flags attribute, they usually will require some kind of conditional testing to be performed. This testing necessitates 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 bit mask to determine if a bit is set to 1. The result of ANDing two bits is 1 only when both bits are 1; otherwise, the result is 0. You 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 you AND the variable lang with the specific bit flag you are testing for (in this case Language.CSharp), you 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 ANDing the bits together returns the value Language.CSharp in the first expression and 0x0000 in the second expression. Comparing this result to the value you are looking for (Language.CSharp) tells you whether that specific bit was turned on.

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

 if(lang == Language.CSharp) 

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

 lang = Language.CSharp; if ((lang != 0) &&(Language.CSharp == (lang | Language.CSharp))) {     // CSharp is found using OR logic. } 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:

 lang = Language.CSharp | Language.VB6 | Language.Cpp; if ((lang != 0) &&(Language.CSharp == (lang | Language.CSharp))) {     // CSharp is found using OR logic. } Language.CSharp 0001 lang 1101 ORed bit values 1101 

The first expression results in the same value as you are testing against. The second expression results in a much larger value than Language.CSharp. This indicates that the variable lang in the first expression contains only the value Language.CSharp, whereas the second expression contains other languages besides Language.CSharp (and may not contain Language.CSharp at all).

Using the OR version of this formula, you can test multiple bits to determine if they are both on and all other bits are off. This is done in the following conditional statement:

 if((lang != 0) && ((lang | (Language.CSharp | Language.VBNET)) ==    (Language.CSharp | Language.VBNET))) 

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

 if((lang != 0) && ((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 ORs together all the values you want to test for. If you wanted to test for all languages except Language.CSharp, your conditional statement(s) would grow quite large and unwieldy. To fix this, you add a value to the Language enumeration that ORs together all languages except Language.CSharp. The new enumeration looks like this:

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

and your conditional statement might look similar to the following:

 if((lang != 0) && (lang | Language.AllLanguagesExceptCSharp) ==     Language. AllLanguagesExceptCSharp) 

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

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



C# Cookbook
Secure Programming Cookbook for C and C++: Recipes for Cryptography, Authentication, Input Validation & More
ISBN: 0596003943
EAN: 2147483647
Year: 2004
Pages: 424

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