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;
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 }
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
0
. 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.
Get C# Cookbook now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.