Perché qualcuno dovrebbe usare l’operatore << in una dichiarazione enum?

Stavo guardando il codice che ho attualmente nel mio progetto e ho trovato qualcosa del genere:

public enum MyEnum { open = 1 << 00, close = 1 << 01, Maybe = 1 << 02, ........ } 

L’operando << è l’operando shift, che sposta il primo operando lasciato dai bit numerici specificati nel secondo operando.

Ma perché qualcuno dovrebbe usare questo in una dichiarazione di enum ?

Questo ti permette di fare qualcosa del genere:

 var myEnumValue = MyEnum.open | MyEnum.close; 

senza dover contare i valori di bit di multipli di 2.

(come questo):

 public enum MyEnum { open = 1, close = 2, Maybe = 4, ........ } 

Questo di solito è usato con bitfield, poiché è chiaro quale sia il pattern, rimuove la necessità di calcolare manualmente i valori corretti e quindi riduce la possibilità di errori

 [Flags] public enum SomeBitField { open = 1 < < 0 //1 closed = 1 << 1 //2 maybe = 1 << 2 //4 other = 1 << 3 //8 ... } 

Per evitare di digitare a mano i valori per un enumerazione delle Flags .

 public enum MyEnum { open = 0x01, close = 0x02, Maybe = 0x04, ........ } 

Questo è per creare un enum che puoi combinare.

Ciò che effettivamente significa è questo:

 public enum MyEnum { open = 1; close = 2; Maybe = 4; //... } 

Questo è solo un metodo più a prova di proiettile per creare un [Flags] .

È solo pensato per essere un modo più pulito / intuitivo di scrivere i bit. 1, 2, 3 è una sequenza più leggibile dall’uomo di 0x1, 0x2, 0x4, ecc.

Molte risposte qui descrivono ciò che questa meccanica ti permette di fare, ma non il motivo per cui vorresti usarlo. Ecco perché.

Versione breve:

Questa notazione aiuta quando si interagisce con altri componenti e si comunica con altri ingegneri perché ti dice esplicitamente quale bit in una parola viene impostato o cancellato invece di oscurare quell’informazione all’interno di un valore numerico.

Quindi potrei chiamarti al telefono e dire “Ehi, che bit è per aprire il file?” E tu diresti, “Bit 0”. E scriverei nel mio codice open = 1 < < 0 . Perché il numero a destra di < < ti dice il numero di bit.

.

Versione lunga:

Tradizionalmente i bit in una parola sono numerati da destra a sinistra, iniziando da zero. Quindi il bit meno significativo è il bit numero 0 e si conta mentre si procede verso il bit più significativo. Ci sono diversi vantaggi nell'etichettare i bit in questo modo.

Un vantaggio è che puoi parlare dello stesso bit indipendentemente dalla dimensione della parola. Ad esempio, potrei dire che sia nella parola a 32 bit 0x384A che nella parola a 8 bit 0x63, i bit 6 e 1 sono impostati. Se hai numerato i tuoi bit nella direzione opposta, non potresti farlo.

Un altro vantaggio è che il valore di un bit è semplicemente 2 elevato alla potenza della posizione del bit. Ad esempio, il binario 0101 ha i bit 2 e 0 impostati. Il bit 2 contribuisce al valore 4 (2^2) al numero e il bit 0 contribuisce al valore 1 (2 ^ 0). Quindi il valore del numero è ovviamente 4 + 1 = 5.

Questa lunga spiegazione di fondo ci porta al punto: la notazione < < ti dice il numero di bit solo guardandolo.

Il numero 1 di per sé nell'istruzione 1 < < n è semplicemente un singolo bit impostato in bit position 0. Quando si sposta quel numero a sinistra, si sposta quindi quel bit impostato su una posizione diversa nel numero. Convenientemente, l'importo che si sposta indica il numero di bit che verrà impostato.

 1 < < 5: This means bit 5. The value is 0x20. 1 << 12: This means bit 12. The value is 0x40000. 1 << 17: This means bit 17. The value is 0x1000000. 1 << 54: This means bit 54. The value is 0x40000000000000. (You can probably see that this notation might be helpful if you're defining bits in a 64-bit number) 

Questa notazione risulta davvero utile quando si interagisce con un altro componente, come la mapping di bit in una parola in un registro hardware. Come se si potesse avere un dispositivo che si accende quando si scrive al bit 7. Quindi l'ingegnere hardware scriverà una scheda tecnica che dice che il bit 7 abilita il dispositivo. E dovresti scrivere nel tuo codice ENABLE = 1 < < 7 . Facile come quello

Oh, spara. L'ingegnere ha appena inviato un errata alla scheda tecnica dicendo che doveva essere il bit 15, non il bit 7. Va bene, basta cambiare il codice in ENABLE = 1 < < 15 .

Cosa ENABLE se ENABLE fosse effettivamente quando entrambi i bit 7 e 1 sono stati impostati contemporaneamente?

ENABLE = (1 < < 7) | (1 << 1) ENABLE = (1 < < 7) | (1 << 1) .

All'inizio potrebbe sembrare strano e ottuso, ma ti ci abituerai. E lo apprezzerai se hai bisogno esplicitamente di conoscere il numero di bit di qualcosa.

È uguale ai poteri di due.

 public enum SomeEnum { Enum1 = 1 < < 0, //1 Enum2 = 1 << 1, //2 Enum3 = 1 << 2, //4 Enum4 = 1 << 3 //8 } 

E con questo enume avrai una funzione che assomiglia a questo:

 void foo(unsigned ind flags) { for (int = 0; i < MAX_NUMS; i++) if (1 << i & flags) { //do some stuff... //parameter to that stuff probably is i either enum value } } 

E chiamare a quella funzione sarebbe foo(Enum2 | Enum3); e farà qualcosa con tutti i valori enum dati.