2011-01-24 5 views
121

Ho un enum come:Come rimuovere un oggetto per un enumerazione OR?

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

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

Come potrei rimuovere il colore blu dai colori variabili?

+1

Piccola nota: un enum bit a bit in C# dovrebbe ottenere l'attributo [Flags] sopra di esso. – Nyerguds

+0

@Nyerguds, potresti spiegare perché dovrebbe ottenere l'attributo? – ethane

+0

Offre un supporto IntelliSense migliore durante il debug, poiché riconosce i valori enum sconosciuti come combinazioni di valori esistenti. – Nyerguds

risposta

216

È necessario & con il ~ (complemento) di 'BLU'.

L'operatore del complemento in pratica inverte o "capovolge" tutti i bit per il tipo di dati specificato. Pertanto, se si utilizza l'operatore AND (&) con un valore (chiamiamolo quel valore 'X') e il complemento di uno o più bit di impostazione (chiamiamo quei bit Q e il loro complemento ~Q), la dichiarazione X & ~Q cancella qualsiasi bit impostati in Q da X e restituiscono il risultato.

Quindi, per rimuovere o cancellare i BLUE bit, è possibile utilizzare la seguente dichiarazione:

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

È inoltre possibile specificare più bit per cancellare, come segue:

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 

Quindi, per riassumere:

  • X | Q insiemi bit (s) Q
  • X & ~Q libera bit (s) Q
  • ~X ribalta/inverte tutti i bit X
+0

quindi se volessi rimuovere di più dovrei semplicemente fare: & = ~ Blah.BLUE & ~ Blah.Green? – Blankman

+0

@Blank: corretto. – SLaks

+10

Migliore è 'colors & = ~ (Blah.BLUE | Blah.GREEN);' – par

7

And not si ...............................

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

Le altre risposte sono corrette, ma per rimuovere specificamente blu da quanto sopra scrivi:

colors &= ~Blah.BLUE; 
+0

Risposta breve e chiara. Queste sono le migliori risposte! – Bitterblue

+0

Dolce. Breve e al punto – Joseph

6

Pensavo che questo potrebbe essere utile per altre persone che sono inciampate qui come me.

Fare attenzione a come si gestiscono i valori di enumerazione che è possibile impostare per avere un valore == 0 (a volte può essere utile avere uno stato Sconosciuto o Inattivo per un enum). Causa problemi quando ci si basa su queste operazioni di manipolazione dei bit.

Anche quando si hanno valori enum che sono combinazioni di altre potenze di 2 valori, ad es.

public enum Colour 
{ 
    None = 0, // default value 
    RED = 2, 
    BLUE = 4, 
    GREEN = 8, 
    YELLOW = 16, 
    Orange = 18 // Combined value of RED and YELLOW 
} 

In questi casi un metodo di estensione di questo tipo potrebbe rivelarsi utile:

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

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

    return states & ~state; 
} 

E anche il metodo isset equivilent che gestisce i valori combinati (anche se un po 'di un modo 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

Mi sembra che la soluzione più semplice sia evitare di usare 0 come bandiera. Normalmente installo enumerazioni come [this] (https://hastebin.com/futuwetipo.swift). Non vedo come tu tragga vantaggio dalla specifica di uno stato con un valore pari a 0. Dopo tutto, il punto è che puoi preoccuparti dei nomi adatti ai programmatori ('Rosso, Blu, Verde') piuttosto che dei valori sottostanti , si? – Sinjai

+0

Avere una voce 'none' o' unknown' o 'unset' con valore == 0 è in molti casi una buona cosa poiché non si può sempre presumere che un determinato valore sia l'insieme predefinito, ad es. se hai solo rosso, blu e verde hai il rosso come valore predefinito (ad esempio il valore che l'enumerazione ha quando viene creato o l'utente non lo ha modificato?) –

+0

Non puoi semplicemente avere Unset = 1 e usa '1, 2, 4, 8' come valori? Se hai bisogno di un valore predefinito, questo è ciò che i costruttori di default sono, giusto? Mi piace mantenere le cose il più esplicite possibile per motivi di leggibilità e fare affidamento su un enum di default a 'default (int)' ('0') quando non viene fornito un valore, nonostante sia un'informazione presumibilmente nota a qualsiasi sviluppatore, è troppo subdolo per i miei gusti comunque. Edit: Oh wait, fare in modo che Unset = 0 impedisca a qualcosa di essere "Unset | Blue'? – Sinjai

1

E xor (^)?

Dato che il FLAG che si sta tentando di rimuovere è lì, funzionerà .. in caso contrario, sarà necessario utilizzare uno &.

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

È possibile utilizzare questo:

colors &= ~Blah.RED; 
Problemi correlati