Небольшое примечание: побитовое перечисление в C # должно получить атрибут [Flags] над ним.
Nyerguds
@ Nyerguds, не могли бы вы объяснить, почему он должен получить атрибут?
этан
Он обеспечивает лучшую поддержку IntelliSense при отладке, поскольку он распознает неизвестные значения перечисления как комбинации существующих значений.
Nyerguds
1
Это также обеспечивает более значимое .ToString()значение. например, RED, BLUE, YELLOWа не 22.
Синджай,
Ответы:
333
Вам нужно &это с ~(дополнением) «СИНИЙ».
Оператор дополнения по существу инвертирует или «переворачивает» все биты для данного типа данных. Таким образом, если вы используете ANDoperator ( &) с некоторым значением (давайте назовем это значение '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
Думал, что это может быть полезно для других людей, которые споткнулись здесь, как я.
Будьте осторожны при обработке любых значений перечисления, для которых вы можете установить значение == 0 (иногда может быть полезно иметь состояние Unknown или Idle для перечисления). Это вызывает проблемы при использовании этих операций манипуляции битами.
Также, когда у вас есть перечислимые значения, которые являются комбинациями другой степени 2 значений, например
publicenumColour{None=0,// default value
RED =2,
BLUE =4,
GREEN =8,
YELLOW =16,Orange=18// Combined value of RED and YELLOW}
В этих случаях такой метод расширения может пригодиться:
publicstaticColourUnSet(thisColour states,Colour state){if((int)states ==0)return states;if(states == state)returnColour.None;return states &~state;}
А также эквивалентный метод IsSet, который обрабатывает объединенные значения (хотя и немного хакерски)
publicstaticboolIsSet(thisColour states,Colour state){// By default if not OR'dif(states == state)returntrue;// Combined: One or more bits need to be setif( state ==Colour.Orange)return0!=(int)(states & state);// Non-combined: all bits need to be setreturn(states & state)== state;}
Мне кажется, что более простое решение - избегать использования 0 в качестве флага. Я обычно устанавливаю перечисления флагов вот так . Я не понимаю, как вам выгодно указывать состояние со значением 0. В конце концов, весь смысл в том, что вы можете позаботиться о дружественных для программиста именах ( Red, Blue, Green), а не о базовых значениях, да?
Синджай,
Наличие noneили unknownили unsetзаписи со значением == 0 во многих случаях хорошо, так как вы не всегда можете предположить, что определенное значение является набором по умолчанию, например, если у вас есть только красный, синий и зеленый, вы будете иметь красный как значение по умолчанию (например, значение, которое enum имеет при его создании или пользователь не изменил его?)
Sverrir Sigmundarson
Разве вы не можете просто установить Unset = 1 и использовать в 1, 2, 4, 8качестве своих значений? Если вам нужно значение по умолчанию, для этого нужны конструкторы по умолчанию, верно? Мне нравится держать вещи настолько явными, насколько это возможно, для удобства чтения, и полагаться на перечисление по умолчанию на default(int)( 0), когда ему не присвоено значение, несмотря на то, что информация, по-видимому, известна любому разработчику, в любом случае слишком подло. Редактировать: Ой, подождите, будет ли Unset = 0 препятствовать чему-либо быть Unset | Blue?
Синджай,
Вы находитесь на правильном пути в вашем редакторе Синджай, сохраняя неустановленное значение == 0 фактически решает несколько проблем. Один из них - то, что вы упомянули, а другой - если вы сбросили все значения перечисления, тогда вам не нужен особый случай для «Unset», если он установлен на ноль. (например, если вы в Red & ~Redитоге получите ноль, вам потребуется код для проверки этого случая и явное присвоение Unsetзначения)
Sverrir Sigmundarson
Попался. Вы часто сталкиваетесь с неустановленными флагами?
Синджай,
2
Что насчет xor (^)?
Учитывая, что FLAG, который вы пытаетесь удалить, есть, он будет работать .. если нет, вам придется использовать &.
publicenumColour{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;
Чтобы упростить перечисление флага и сделать его лучше читаемым, избегая кратных, мы можем использовать сдвиг битов. (Из хорошей статьи « Завершение великой дискуссии о флагах Enum» )
[FLAG]EnumBlah{
RED =1,
BLUE =1<<1,
GREEN =1<<2,
YELLOW =1<<3}
.ToString()
значение. например,RED, BLUE, YELLOW
а не22
.Ответы:
Вам нужно
&
это с~
(дополнением) «СИНИЙ».Оператор дополнения по существу инвертирует или «переворачивает» все биты для данного типа данных. Таким образом, если вы используете
AND
operator (&
) с некоторым значением (давайте назовем это значение 'X') и дополнением одного или нескольких установленных битов (назовем эти битыQ
и их дополнение~Q
), операторX & ~Q
очищает все биты, которые были установлены вQ
отX
и возвращает результат.Таким образом, чтобы удалить или очистить
BLUE
биты, вы используете следующее утверждение:Вы также можете указать несколько битов для очистки следующим образом:
или поочередно ...
Итак, подведем итог:
X | Q
устанавливает бит (ы)Q
X & ~Q
очищает битQ
~X
переворачивает / инвертирует все биты вX
источник
colors &= ~( Blah.BLUE | Blah.GREEN );
Другие ответы верны, но для того, чтобы специально удалить синий цвет из вышеперечисленного, вы должны написать:
источник
And not
Это...............................источник
Думал, что это может быть полезно для других людей, которые споткнулись здесь, как я.
Будьте осторожны при обработке любых значений перечисления, для которых вы можете установить значение == 0 (иногда может быть полезно иметь состояние Unknown или Idle для перечисления). Это вызывает проблемы при использовании этих операций манипуляции битами.
Также, когда у вас есть перечислимые значения, которые являются комбинациями другой степени 2 значений, например
В этих случаях такой метод расширения может пригодиться:
А также эквивалентный метод IsSet, который обрабатывает объединенные значения (хотя и немного хакерски)
источник
Red, Blue, Green
), а не о базовых значениях, да?none
илиunknown
илиunset
записи со значением == 0 во многих случаях хорошо, так как вы не всегда можете предположить, что определенное значение является набором по умолчанию, например, если у вас есть только красный, синий и зеленый, вы будете иметь красный как значение по умолчанию (например, значение, которое enum имеет при его создании или пользователь не изменил его?)1, 2, 4, 8
качестве своих значений? Если вам нужно значение по умолчанию, для этого нужны конструкторы по умолчанию, верно? Мне нравится держать вещи настолько явными, насколько это возможно, для удобства чтения, и полагаться на перечисление по умолчанию наdefault(int)
(0
), когда ему не присвоено значение, несмотря на то, что информация, по-видимому, известна любому разработчику, в любом случае слишком подло. Редактировать: Ой, подождите, будет ли Unset = 0 препятствовать чему-либо бытьUnset | Blue
?Red & ~Red
итоге получите ноль, вам потребуется код для проверки этого случая и явное присвоениеUnset
значения)Что насчет xor (^)?
Учитывая, что FLAG, который вы пытаетесь удалить, есть, он будет работать .. если нет, вам придется использовать &.
источник
Чтобы упростить перечисление флага и сделать его лучше читаемым, избегая кратных, мы можем использовать сдвиг битов. (Из хорошей статьи « Завершение великой дискуссии о флагах Enum» )
а также очистить все биты
источник
Вы можете использовать это:
источник