What is the meaning of the conditional expression for checking DrawItemState equivalence in Windows Forms?

Viewed 118

I was reading the DrawItemState documentation and I encountered the following snippet of code:

if ((e.State & DrawItemState.Selected) == DrawItemState.Selected )
          brush = SystemBrushes.HighlightText;

The following explanation was given in the documentation

Since state can be a combination (bit-flag) of enum values, you can't use "==" to compare them

However I still do not understand how this conditional expression is different from the snippet shown below:

if (e.State == DrawItemState.Selected )
          brush = SystemBrushes.HighlightText;

Also, I don't understand how the bitwise AND & operator makes a difference and why it is even included in the conditional expression.

1 Answers

Because of the underlying values of the enum, you can set multiple values (bitwise combination):

var state = DrawItemState.Disabled | DrawItemState.Grayed;

That means that these will both return false:

Console.WriteLine(state == DrawItemState.Disabled);  // false
Console.WriteLine(state == DrawItemState.Grayed);    // false

One way to test the values is with the bitwise "and" operator:

Console.WriteLine((state & DrawItemState.Grayed) == DrawItemState.Grayed);  // true

Essentially, state in my example has two bits set - for "Grayed" and "Disabled". By using the bitwise "and" operator with the value of "Grayed", the result is also the value of "Grayed".

0 0 0 0 0 0 0 0 1 1 0    // binary value of disabled and grayed

0 0 0 0 0 0 0 0 0 1 0    // binary value of grayed

0 0 0 0 0 0 0 0 0 1 0    // result is same value as grayed

You could test for multiple flags too:

Console.WriteLine((state & (DrawItemState.Grayed | DrawItemState.Disabled))
                  == (DrawItemState.Grayed | DrawItemState.Disabled));  // true

0 0 0 0 0 0 0 0 1 1 0    // binary value of disabled and grayed

0 0 0 0 0 0 0 0 1 1 0    // binary value of disabled and grayed

0 0 0 0 0 0 0 0 1 1 0    // result is same value as disabled and grayed

Personally, I think it's easier to test for flag values using HasFlag:

Console.WriteLine(state.HasFlag(DrawItemState.Grayed));  // true

Note that if there's just one value, then == will work, but for a "flags" enumeration that supports a bitwise combination, that's never a guarantee.

var state = DrawItemState.Grayed;

Console.WriteLine(state == DrawItemState.Grayed);  // true
Related