How to remove an item for a OR'd enum?

C#Enums

C# Problem Overview


I have an enum like:

public enum Blah
{
    RED = 2,
    BLUE = 4,
    GREEN = 8,
    YELLOW = 16
}

Blah colors = Blah.RED | Blah.BLUE | Blah.YELLOW;

How could I remove the color blue from the variable colors?

C# Solutions


Solution 1 - C#

You need to & it with the ~ (complement) of 'BLUE'.

The complement operator essentially reverses or 'flips' all bits for the given data type. As such, if you use the AND operator (&) with some value (let's call that value 'X') and the complement of one or more set bits (let's call those bits Q and their complement ~Q), the statement X & ~Q clears any bits that were set in Q from X and returns the result.

So to remove or clear the BLUE bits, you use the following statement:

colorsWithoutBlue = colors & ~Blah.BLUE
colors &= ~Blah.BLUE // This one removes the bit from 'colors' itself

You can also specify multiple bits to clear, as follows:

colorsWithoutBlueOrRed = colors & ~(Blah.BLUE | Blah.RED)
colors &= ~(Blah.BLUE | Blah.RED) // This one removes both bits from 'colors' itself

or alternately...

colorsWithoutBlueOrRed = colors & ~Blah.BLUE & ~Blah.RED
colors &= ~Blah.BLUE & ~Blah.RED // This one removes both bits from 'colors' itself

So to summarize:

  • X | Q sets bit(s) Q
  • X & ~Q clears bit(s) Q
  • ~X flips/inverts all bits in X

Solution 2 - C#

The other answers are correct, but to specifically remove blue from the above you would write:

colors &= ~Blah.BLUE;

Solution 3 - C#

And not it...............................

Blah.RED | Blah.YELLOW == 
   (Blah.RED | Blah.BLUE | Blah.YELLOW) & ~Blah.BLUE;

Solution 4 - C#

Thought this might be useful for other people that stumbled here like me.

Be careful how you handle any enum values that you might set to have a value == 0 (sometimes it can be helpful to have a Unknown or Idle state for an enum). It causes problems when relying on these bit manipulation operations.

Also when you have enum values that are combinations of other power of 2 values, e.g.

public enum Colour
{
    None = 0,  // default value
    RED = 2,
    BLUE = 4,
    GREEN = 8,
    YELLOW = 16,
    Orange = 18  // Combined value of RED and YELLOW
}

In these cases an extension method such as this might come in handy:

public static Colour UnSet(this Colour states, Colour state)
{
    if ((int)states == 0)
        return states;

    if (states == state)
        return Colour.None;

    return states & ~state;
}

And also the equivilent IsSet method that handles the combined values (albeit in a bit of a hacky way)

public static bool IsSet(this Colour states, Colour state)
{
    // By default if not OR'd
    if (states == state)
        return true;

    // Combined: One or more bits need to be set
    if( state == Colour.Orange )
        return 0 != (int)(states & state);
            
    // Non-combined: all bits need to be set
    return (states & state) == state;
}

Solution 5 - C#

To simplify the flag enum and make it may be better to read by avoiding multiples, we can use bit shifting. (From a good article Ending the Great Debate on Enum Flags)

[FLAG]
Enum Blah
{
   RED = 1,
   BLUE = 1 << 1,
   GREEN = 1 << 2,
   YELLOW = 1 << 3
}

and also to clear all bits

private static void ClearAllBits()
{
    colors = colors & ~colors;
}

Solution 6 - C#

What about xor(^)?

Given that the FLAG you are trying to remove is there, it will work.. if not, you will have to use an &.

public enum Colour
{
    None = 0,  // default value
    RED = 2,
    BLUE = 4,
    GREEN = 8,
    YELLOW = 16,
    Orange = 18  // Combined value of RED and YELLOW
}

colors = (colors ^ Colour.RED) & colors;

Solution 7 - C#

You can use this:

colors &= ~Blah.RED; 

Solution 8 - C#

If you use the duckface operator, you don't have to invert bits with ~

color ^= Color.Red; // unset Color.Red

or

color ^= (Color.Red | Color.Blue); // unset both Red and Blue

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionBlankmanView Question on Stackoverflow
Solution 1 - C#SLaksView Answer on Stackoverflow
Solution 2 - C#parView Answer on Stackoverflow
Solution 3 - C#Daniel A. WhiteView Answer on Stackoverflow
Solution 4 - C#Sverrir SigmundarsonView Answer on Stackoverflow
Solution 5 - C#Matt AllenView Answer on Stackoverflow
Solution 6 - C#user4509414View Answer on Stackoverflow
Solution 7 - C#Majid gharaeiView Answer on Stackoverflow
Solution 8 - C#MichaelView Answer on Stackoverflow