如何删除OR'd枚举的项目?

Bla*_*man 163 c# enums

我有一个像:

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

Blah colors = Blah.RED | Blah.BLUE | Blah.YELLOW;
Run Code Online (Sandbox Code Playgroud)

如何从可变颜色中删除蓝色?

SLa*_*aks 298

你需要&使用~'补充'的'蓝色'.

补码运算符实质上反转或"翻转"给定数据类型的所有位.因此,如果您使用带有某个值的ANDoperator(&)(让我们调用该值'X')和一个或多个设置位的补码(让我们调用那些位Q及其补码~Q),该语句将X & ~Q清除在中设置的任何位.Q来自X并返回结果.

因此,要删除或清除这些BLUE位,请使用以下语句:

colorsWithoutBlue = colors & ~Blah.BLUE
colors &= ~Blah.BLUE // This one removes the bit from 'colors' itself
Run Code Online (Sandbox Code Playgroud)

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

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

或者......

colorsWithoutBlueOrRed = colors & ~Blah.BLUE & ~Blah.RED
colors &= ~Blah.BLUE & ~Blah.RED // This one removes both bits from 'colors' itself
Run Code Online (Sandbox Code Playgroud)

总结一下:

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

  • 更好的是`colors&=〜(Blah.BLUE | Blah.GREEN);` (10认同)
  • 多么不寻常,我只是在5天前仍在考虑如何再次执行此操作:)这个问题已在我的收件箱中更新,瞧! (2认同)

par*_*par 43

其他答案是正确的,但要从上面特别删除蓝色,你会写:

colors &= ~Blah.BLUE;
Run Code Online (Sandbox Code Playgroud)


Dan*_*ite 9

And not 它...............................

Blah.RED | Blah.YELLOW == 
   (Blah.RED | Blah.BLUE | Blah.YELLOW) & ~Blah.BLUE;
Run Code Online (Sandbox Code Playgroud)


Sve*_*son 7

认为这可能对像我这样偶然发现的其他人有用.

请注意如何处理您可能设置为具有值== 0的任何枚举值(有时,对于枚举具有"未知"或"空闲"状态会有所帮助).当依赖这些位操作操作时,它会导致问题.

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

public enum Colour
{
    None = 0,  // default value
    RED = 2,
    BLUE = 4,
    GREEN = 8,
    YELLOW = 16,
    Orange = 18  // Combined value of RED and YELLOW
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

    return states & ~state;
}
Run Code Online (Sandbox Code Playgroud)

以及处理组合值的等效IsSet方法(虽然有点像hacky方式)

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;
}
Run Code Online (Sandbox Code Playgroud)

  • 我知道这很旧,但是对于您的 Unset 方法,如果 `states == 0` 那么 `states & ~state == states` 所以不需要您的第一个分支。同样,如果“states == state”,则“states & ~state == Colour.None”,因此不需要第二个分支,您只需返回“states & ~state”... (3认同)
  • 在许多情况下,具有 value == 0 的“none”或“unknown”或“unset”条目是一件好事,因为您不能总是假设特定值是默认设置,例如,如果您只有红色、蓝色和绿色您是否要将红色作为默认值(例如,枚举在创建时或用户未修改它时具有的值?) (2认同)

Mat*_*len 5

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

[FLAG]
Enum Blah
{
   RED = 1,
   BLUE = 1 << 1,
   GREEN = 1 << 2,
   YELLOW = 1 << 3
}
Run Code Online (Sandbox Code Playgroud)

并清除所有位

private static void ClearAllBits()
{
    colors = colors & ~colors;
}
Run Code Online (Sandbox Code Playgroud)