我有一个枚举:

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

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

我如何从可变颜色中移除蓝色?


而不是它...............................

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

你需要用'BLUE'的~(补语)加上它。

补操作符本质上是反转或“翻转”给定数据类型的所有位。因此,如果你将AND操作符(&)与某个值(我们称该值为'X')和一个或多个集位的补位(我们称这些位为Q及其补位~Q)一起使用,语句X & ~Q将X中Q中设置的所有位清除并返回结果。

所以要移除或清除BLUE位,你可以使用下面的语句:

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

您也可以指定多个要清除的位,如下所示:

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

或交替…

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

总结一下:

X | Q设置位Q X & ~Q清除位Q ~X翻转/反转X中的所有位


其他答案都是正确的,但是为了从上面的选项中去除蓝色,你可以这样写:

colors &= ~Blah.BLUE;

我想这对其他像我一样跌跌撞撞来到这里的人可能有用。

注意如何处理可能设置为值== 0的枚举值(有时为枚举设置Unknown或Idle状态会有帮助)。当依赖于这些位操作时,它会引起问题。

此外,当您有枚举值是2的其他幂值的组合时,例如。

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

在这些情况下,像这样的扩展方法可能会派上用场:

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

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

    return states & ~state;
}

还有等效的IsSet方法,它处理组合值(尽管以一种有点俗气的方式)

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;
}

那么xor(^)呢?

考虑到你想要移除的旗帜就在那里,它会起作用。如果不是,则必须使用&。

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;

你可以用这个:

colors &= ~Blah.RED; 

为了简化标志枚举,并通过避免倍数来更好地读取,我们可以使用位移位。 (摘自一篇好文章《结束关于旗帜的大争论》)

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

还要清除所有比特

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

要切换标志,您可以使用duckface操作符,而不必使用~反转位

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

or

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

但是,这将切换标志,而不是清除它。

正如@daniil-palii所提到的那样,编辑以确保正确性