Как удалить элемент для перечисления OR'd? - PullRequest
152 голосов
/ 24 января 2011

У меня есть перечисление как:

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

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

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

Ответы [ 7 ]

278 голосов
/ 24 января 2011

Вам нужно & это с ~ (дополнением) 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 переворачивает / инвертирует все биты вX
41 голосов
/ 24 января 2011

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

colors &= ~Blah.BLUE;
8 голосов
/ 24 января 2011

And not это ...............................

Blah.RED | Blah.YELLOW == 
   (Blah.RED | Blah.BLUE | Blah.YELLOW) & ~Blah.BLUE;
7 голосов
/ 01 марта 2012

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

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

А как насчет 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;
0 голосов
/ 11 июля 2019

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

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

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

private static void ClearAllBits()
{
    colors = colors & ~colors;
}
0 голосов
/ 19 октября 2017

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

colors &= ~Blah.RED; 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...