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 variablelangin the following line of code con- tains a language such asLanguage.CSharp and/orLanguage.Cpp:
Language lang = Language.CSharp | Language.VBNET;
816 | Chapter 20: Numbers and Enumerations
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 fol- lowing 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 enumerationsare used asbit flagsand are marked with the Flags attribute, they usually will require some kind of conditional testing to be performed. This test- ing 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 condi- tional statement:
if((lang & Language.CSharp) == Language.CSharp)
wherelang is of theLanguage enumeration type.
The&operator is used with a bit mask to determine if a bit is set to1. The result of ANDing two bitsis1only when both bitsare1; otherwise, the result is 0. You can use this operation to determine if a specific bit flag is set to a1in the number con- taining the individual bit flags. If you AND the variablelangwith the specific bit flag you are testing for (in this case,Language.CSharp), you can extract that single specific
Determining Whether One or More Enumeration Flags Are Set | 817 bit flag. The expression (lang & Language.CSharp) issolved in the following manner if lang is equal toLanguage.CSharp:
Language.CSharp 0001 lang 0001 ANDed bit values 0001
Iflangisequal to another value, such asLanguage.VBNET, the expression is solved in the following manner:
Language.CSharp 0001 lang 0010 ANDed bit values 0000
Notice that ANDing the bitstogether returnsthe valueLanguage.CSharp in the first expression and0x0000in the second expression. Comparing this result to the value you are looking for (Language.CSharp) tellsyou whether that specific bit wasturned 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 bitsturned on)? To test if only theLanguage.CSharp bit isturned on in the variablelang, you can use the following conditional statement:
if(lang == Language.CSharp)
Consider if the variablelangcontained only the valueLanguage.CSharp. The expres- sion 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 variablelangand perform the same opera- tion onlang:
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
818 | Chapter 20: Numbers and Enumerations
The first expression results in the same value as you are testing against. The second expression results in a much larger value thanLanguage.CSharp. Thisindicatesthat 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 containLanguage.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 bitsare off. Thisisdone 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 ORstogether all the valuesyou want to test for. If you wanted to test for all languages except Language.CSharp, your conditional state- ment(s) would grow quite large and unwieldy. To fix this, you add a value to the Languageenumeration that ORstogether all languagesexceptLanguage.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.
Determining the Integral Part of a Decimal or Double | 819