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

后端 未结 7 1700
后悔当初
后悔当初 2020-12-22 18:17

I have an enum like:

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

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


        
相关标签:
7条回答
  • 2020-12-22 18:43

    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;
    }
    
    0 讨论(0)
  • 2020-12-22 18:44

    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;
    
    0 讨论(0)
  • 2020-12-22 18:58

    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;
    }
    
    0 讨论(0)
  • 2020-12-22 18:59

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

    colors &= ~Blah.BLUE;
    
    0 讨论(0)
  • 2020-12-22 19:00

    You can use this:

    colors &= ~Blah.RED; 
    
    0 讨论(0)
  • 2020-12-22 19:03

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

    Blah.RED | Blah.YELLOW == 
       (Blah.RED | Blah.BLUE | Blah.YELLOW) & ~Blah.BLUE;
    
    0 讨论(0)
提交回复
热议问题