Pequeña nota: una enumeración bit a bit en C # debería obtener el atributo [Flags] por encima de él.
Nyerguds
@Nyerguds, ¿podría explicar por qué debería obtener el atributo?
etano
Ofrece una mejor compatibilidad con IntelliSense durante la depuración, porque reconoce valores de enumeración desconocidos como combinaciones de valores existentes.
Nyerguds
1
También proporciona un .ToString()valor más significativo . por ejemplo, en RED, BLUE, YELLOWlugar de 22.
Sinjai
Respuestas:
331
Lo necesitas &con el ~(complemento) de 'AZUL'.
El operador del complemento esencialmente invierte o 'voltea' todos los bits para el tipo de datos dado. Como tal, si usa el ANDoperador (& ) con algún valor (llamemos a ese valor 'X') y el complemento de uno o más bits de conjunto (llamemos a esos bits Qy su complemento ~Q), la instrucción X & ~Qborra todos los bits que se establecieron en Qde Xy devuelve el resultado.
Entonces, para eliminar o borrar los BLUEbits, use la siguiente declaración:
colorsWithoutBlue = colors &~Blah.BLUE
colors &=~Blah.BLUE // This one removes the bit from 'colors' itself
También puede especificar varios bits para borrar, de la siguiente manera:
colorsWithoutBlueOrRed = colors &~(Blah.BLUE |Blah.RED)
colors &=~(Blah.BLUE |Blah.RED)// This one removes both bits from 'colors' itself
o alternativamente ...
colorsWithoutBlueOrRed = colors &~Blah.BLUE &~Blah.RED
colors &=~Blah.BLUE &~Blah.RED // This one removes both bits from 'colors' itself
Pensé que esto podría ser útil para otras personas que tropezaron aquí como yo.
Tenga cuidado al manejar cualquier valor de enumeración que pueda establecer para tener un valor == 0 (a veces puede ser útil tener un estado Desconocido o Inactivo para una enumeración). Causa problemas al confiar en estas operaciones de manipulación de bits.
También cuando tiene valores de enumeración que son combinaciones de otra potencia de 2 valores, p. Ej.
publicenumColour{None=0,// default value
RED =2,
BLUE =4,
GREEN =8,
YELLOW =16,Orange=18// Combined value of RED and YELLOW}
En estos casos, un método de extensión como este podría ser útil:
publicstaticColourUnSet(thisColour states,Colour state){if((int)states ==0)return states;if(states == state)returnColour.None;return states &~state;}
Y también el método IsSet equitativo que maneja los valores combinados (aunque de una manera un poco hacky)
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;}
Me parece que la solución más simple es evitar usar 0 como bandera. Por lo general, configuro enums de bandera como este . No veo cómo se beneficia al especificar un estado con un valor de 0. Después de todo, el punto es que puede preocuparse por los nombres amigables para el programador ( Red, Blue, Green) en lugar de los valores subyacentes, ¿sí?
Sinjai
Tener una noneo unknowno unsetentrada con el valor == 0 es en muchos casos una buena cosa ya que no siempre se puede asumir que un valor particular es el conjunto predeterminado, por ejemplo, si sólo tiene rojo, azul y verde que se van a tener como Rojo el valor predeterminado (por ejemplo, el valor que tiene la enumeración cuando se crea o el usuario no lo ha modificado)
Sverrir Sigmundarson
¿No puede simplemente tener Unset = 1 y usar 1, 2, 4, 8como sus valores? Si necesita un valor predeterminado, para eso están los constructores predeterminados, ¿verdad? Me gusta mantener las cosas lo más explícitas posible en aras de la legibilidad, y confiar en una enumeración predeterminada default(int)( 0) cuando no se le da un valor, a pesar de ser información presumiblemente conocida por cualquier desarrollador, de todos modos es demasiado astuto para mis gustos. Editar: Oh, espera, ¿hacer Unset = 0 evitaría que algo sea Unset | Blue?
Sinjai
Está en el camino correcto en su edición Sinjai, manteniendo el valor no establecido == 0 en realidad resuelve algunos problemas. Uno es lo que mencionó y otro es si desarma todos los valores de enumeración, entonces no necesita un caso especial para "Desarmar" si está puesto a cero. (por ejemplo, si Red & ~Redtermina con cero, entonces tendría que tener un código para verificar este caso y asignar explícitamente el Unsetvalor)
Sverrir Sigmundarson
Gotcha ¿A menudo te encuentras lidiando con banderas no configuradas?
Sinjai
2
¿Qué pasa con xor (^)?
Dado que la BANDERA que está tratando de eliminar está allí, funcionará ... si no, tendrá que usar un &.
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;
Para simplificar la enumeración de la bandera y hacer que sea mejor leer evitando los múltiplos, podemos usar el desplazamiento de bits. (De un buen artículo Terminando el Gran Debate sobre Enum Flags )
[FLAG]EnumBlah{
RED =1,
BLUE =1<<1,
GREEN =1<<2,
YELLOW =1<<3}
.ToString()
valor más significativo . por ejemplo, enRED, BLUE, YELLOW
lugar de22
.Respuestas:
Lo necesitas
&
con el~
(complemento) de 'AZUL'.El operador del complemento esencialmente invierte o 'voltea' todos los bits para el tipo de datos dado. Como tal, si usa el
AND
operador (&
) con algún valor (llamemos a ese valor 'X') y el complemento de uno o más bits de conjunto (llamemos a esos bitsQ
y su complemento~Q
), la instrucciónX & ~Q
borra todos los bits que se establecieron enQ
deX
y devuelve el resultado.Entonces, para eliminar o borrar los
BLUE
bits, use la siguiente declaración:También puede especificar varios bits para borrar, de la siguiente manera:
o alternativamente ...
Entonces para resumir:
X | Q
establece bit (s)Q
X & ~Q
borra bit (s)Q
~X
voltea / invierte todos los bits enX
fuente
colors &= ~( Blah.BLUE | Blah.GREEN );
Las otras respuestas son correctas, pero para eliminar específicamente el azul de lo anterior, escribiría:
fuente
And not
eso...............................fuente
Pensé que esto podría ser útil para otras personas que tropezaron aquí como yo.
Tenga cuidado al manejar cualquier valor de enumeración que pueda establecer para tener un valor == 0 (a veces puede ser útil tener un estado Desconocido o Inactivo para una enumeración). Causa problemas al confiar en estas operaciones de manipulación de bits.
También cuando tiene valores de enumeración que son combinaciones de otra potencia de 2 valores, p. Ej.
En estos casos, un método de extensión como este podría ser útil:
Y también el método IsSet equitativo que maneja los valores combinados (aunque de una manera un poco hacky)
fuente
Red, Blue, Green
) en lugar de los valores subyacentes, ¿sí?none
ounknown
ounset
entrada con el valor == 0 es en muchos casos una buena cosa ya que no siempre se puede asumir que un valor particular es el conjunto predeterminado, por ejemplo, si sólo tiene rojo, azul y verde que se van a tener como Rojo el valor predeterminado (por ejemplo, el valor que tiene la enumeración cuando se crea o el usuario no lo ha modificado)1, 2, 4, 8
como sus valores? Si necesita un valor predeterminado, para eso están los constructores predeterminados, ¿verdad? Me gusta mantener las cosas lo más explícitas posible en aras de la legibilidad, y confiar en una enumeración predeterminadadefault(int)
(0
) cuando no se le da un valor, a pesar de ser información presumiblemente conocida por cualquier desarrollador, de todos modos es demasiado astuto para mis gustos. Editar: Oh, espera, ¿hacer Unset = 0 evitaría que algo seaUnset | Blue
?Red & ~Red
termina con cero, entonces tendría que tener un código para verificar este caso y asignar explícitamente elUnset
valor)¿Qué pasa con xor (^)?
Dado que la BANDERA que está tratando de eliminar está allí, funcionará ... si no, tendrá que usar un &.
fuente
Para simplificar la enumeración de la bandera y hacer que sea mejor leer evitando los múltiplos, podemos usar el desplazamiento de bits. (De un buen artículo Terminando el Gran Debate sobre Enum Flags )
y también para borrar todos los bits
fuente
Puedes usar esto:
fuente