Подтвердить что ты не робот

Как удалить элемент для OR'd перечисления?

У меня есть перечисление вроде:

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

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

Как я могу удалить синий цвет из цветов переменных?

4b9b3361

Ответ 1

Вам нужно & его с помощью ~ (дополнение) 'BLUE'.

Оператор дополнения существенно меняет или "переворачивает" все биты для данного типа данных. Таким образом, если вы используете оператор AND (&) с некоторым значением (позвольте этому значению "X" ) и дополнением к одному или нескольким установленным битам (позвольте вызывать эти биты Q и их дополнение ~Q), оператор X & ~Q очищает любые биты, которые были установлены в Q из X, и возвращает результат.

Итак, чтобы удалить или очистить бит 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 flips/инвертирует все биты в X

Ответ 2

Другие ответы верны, но для того, чтобы специально удалить синий из вышесказанного, вы должны написать:

colors &= ~Blah.BLUE;

Ответ 3

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

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

Ответ 4

Думал, что это может быть полезно для других людей, которые спотыкались здесь, как я.

Будьте осторожны с тем, как вы обрабатываете любые значения перечисления, которые вы можете установить, чтобы иметь value == 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;
}

Ответ 5

Как насчет xor (^)?

Учитывая, что FLAG, который вы пытаетесь удалить, есть, он будет работать. Если нет, вам нужно будет использовать &.

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;

Ответ 6

Вы можете использовать это:

colors &= ~Blah.RED; 

Ответ 7

Чтобы упростить перечисление флага и сделать его лучше читаемым, избегая кратных, мы можем использовать сдвиг битов. (Из хорошей статьи " Завершение великой дискуссии о флагах Enum")

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

а также очистить все биты

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