2011-01-24 12 views
121

tengo una enumeración como:¿Cómo eliminar un artículo para una enumeración OR?

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

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

¿Cómo podría eliminar el color azul de los colores variables?

+1

pequeña nota: una enumeración bit a bit en C# debe recibir todo el [Banderas] atributo por encima de ella. – Nyerguds

+0

@Nyerguds, ¿podría explicar por qué debería obtener el atributo? – ethane

+0

Ofrece una mejor compatibilidad con IntelliSense durante la depuración, ya que reconoce valores de enum desconocidos como combinaciones de valores existentes. – Nyerguds

Respuesta

216

Es necesario & 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 utiliza el operador AND (&) con algún valor (llamemos a ese valor 'X') y el complemento de uno o más bits establecidos (llamemos a esos bits Q y su complemento ~Q), la declaración X & ~Q borra cualquier bits que se establecieron en Q desde X y devuelve el resultado.

Así que para eliminar o borrar los bits de BLUE, se utiliza la siguiente declaración:

colorsWithoutBlue = colors & ~Blah.BLUE 
colors &= ~Blah.BLUE // This one removes the bit from 'colors' itself 

También puede especificar múltiples 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 

Entonces, para resumir:

  • X | Q conjuntos de bit (s) Q
  • X & ~Q despeja bit (s) Q
  • ~X voltea/invierte todos los bits en X
+0

así que si quisiera eliminar más simplemente lo haría: & = ~ Blah.BLUE & ~ Blah.Green? – Blankman

+0

@Blank: Correcto. – SLaks

+10

Mejor es 'colors & = ~ (Blah.BLUE | Blah.GREEN);' – par

7

And not que ...............................

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

Las otras respuestas son correctas, pero para eliminar específicamente azul de arriba usted escribiría:

colors &= ~Blah.BLUE; 
+0

Respuesta corta y clara. Estas son las mejores respuestas! – Bitterblue

+0

Dulce. Breve y al punto – Joseph

6

Pensé que esto podría ser útil para otras personas que tropezaron aquí como yo.

Tenga cuidado de cómo manejar cualquier valor enum 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 enum que son combinaciones de otras potencias de 2 valores, p.

public enum Colour 
{ 
    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 de este tipo puede ser útil:

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

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

    return states & ~state; 
} 

Y también el método Isset equivilent que se encarga de los valores combinados (aunque en un poco de una manera 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; 
} 
+0

Me parece que la solución más simple es evitar el uso de 0 como indicador. Normalmente configuro enum de banderas como [esto] (https://hastebin.com/futuwetipo.swift). No veo cómo te beneficias al especificar un estado con un valor de 0. Después de todo, el punto es que puedes preocuparte por los nombres amigables para programadores ('Rojo, Azul, Verde') en lugar de los valores subyacentes ¿Si? – Sinjai

+0

Tener una entrada 'none' o' unknown' or 'unset' con valor == 0 es en muchos casos algo bueno ya que no siempre se puede asumir que un valor particular es el conjunto predeterminado, p. si solo tiene Rojo, Azul y Verde, ¿tendrá Rojo como valor predeterminado (por ejemplo, el valor que tiene la enumeración cuando se creó o el usuario no lo ha modificado?) –

+0

¿No puede simplemente tener Unset = 1 y usa '1, 2, 4, 8' como tus valores? Si necesita un valor predeterminado, para eso están los constructores predeterminados, ¿verdad? Me gusta mantener las cosas tan explícitas como sea posible por el bien de la legibilidad, y confiar en una enumeración predeterminada para 'default (int)' ('0') cuando no se le da un valor, a pesar de ser información supuestamente conocida por cualquier desarrollador, demasiado furtivo para mis gustos de todos modos. Editar: Oh, espera, haría Unset = 0 evitar que algo sea 'Unset | Azul'? – Sinjai

1

¿Qué hay de xor (^)?

Dado que la BANDERA que está tratando de eliminar está allí, funcionará ... si no, tendrá que usar un &.

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

Puede utilizar esta:

colors &= ~Blah.RED; 
Cuestiones relacionadas