2012-09-19 13 views
12

Potrebbe essere una domanda facile e semplice ma ho ancora un po 'di confusione il motivo per cui si decide di usare bit per bit OR. Si supponga Ho una classe A con quattro campi:Perché l'operatore OR bit a bit viene utilizzato in flag enum con il significato AND

class A 
{ 
    private int Field1; 
    private static int Field2; 
    public int Field3; 
    public static int Field4; 
} 

E utilizzare Reflection per ottenere i campi:

var fields = typeof (A).GetFields(BindingFlags.Public | BindingFlags.Static); 

Se siete newbie con Reflection e non so il modo come utilizzare BindingFlags, il la logica iniziale nella tua testa sarebbe:

Questa riga selezionerà tutti i campi pubblici O statici perché OR bit a bit viene utilizzato. E l'atteso risultato si pensa:

Field2 
Field3 
Field4 

Ma quando colpisce F5, il risultato sarà totalmente diverso, bit per bit OR opere come AND:

Field4 

perché non utilizzare AND bit a bit operatore che potrebbero seguire con la pensiero logico. in questo modo:

var fields = typeof (A).GetFields(BindingFlags.Public & BindingFlags.Static); 

ho trovato parole MSDN:

l'operazione OR bit a bit utilizzato per combinare le bandiere potrebbe essere considerato un concetto avanzato in alcune circostanze che non dovrebbe essere richiesto per compiti semplici.

Si prega chiunque potrebbe spiegare il concetto anticipo qui in modo semplice per la comprensione?

+1

'OR' sembra essere il concetto giusto quando si considera la differenza tra OR inclusivo ed esclusivo. In questo caso il 'OR' è inclusivo, lo stesso che dire" prendi alcuni oggetti dal negozio che contengono uova o prosciutto ". È diverso dal dire "che contengono uova e prosciutto". –

+0

in [MSDN] (http://msdn.microsoft.com/en-us/library/6ztex2dc.aspx) si legge: È necessario specificare BindingFlags.Instance ** o ** BindingFlags.Static per ottenere un ritorno . Quindi potrebbe non essere possibile elencare istanze ** e ** statiche contemporaneamente ... ?? – tschmit007

+0

@ tschmit007: che cosa ha a che fare con la domanda? –

risposta

25

Vedere la fine per un breve riassunto.

Risposta lunga:

OR bit combina i bit dei flag enum.

Esempio:

  • BindingFlags.Public ha il valore di 16 o 10000 (binario)
  • BindingFlags.Static ha il valore di 8 o 1000 (binario)

OR bit a bit combina questi come il seguente :

10000 
01000 
-- 
11000 --> 24 

bit a bit E li unirebbe lik e questo:

10000 
01000 
-- 
00000 --> 0 

Questo è un concetto molto semplice di bandiere:
Ogni valore è una potenza di due, per esempio:

  • 1 = 2^0
  • 2 = 2^1
  • 4 = 2^2
  • 8 = 2^3
  • ecc

loro rappresentazione bit è sempre un 1 e il resto zeri :

Combinare uno di essi usando bit a AND E porta sempre a 0 in quanto non ci sono 1 nella stessa posizione. Bitwise AND porterebbe a una perdita di informazioni completa.

Bitwise OR d'altra parte produce sempre risultati non ambigui. Per esempio, quando hai (binario) 1010 (decimale 10) sai che originariamente era 8 e 2. Non c'è altra possibilità che 10 possa essere stata creata.
Come ha detto di default, il metodo chiamato in seguito possono estrarre queste informazioni utilizzando il bit a bit ed esercente:

if(10 & 8 == 8) // value 8 was set 

L'OR bit a bit in questo caso è fondamentalmente un veicolo per il trasporto dei valori per il metodo che si sta chiamando.
Cosa fa questo metodo con questi valori non ha nulla a che fare con l'uso di OR bit a bit.
Può internaly richiedere che TUTTI i flag passati corrispondano come nel caso di GetFields. Ma potrebbe anche richiedere solo una delle bandiere passate da abbinare.

Per voi come un chiamante, il seguente sarebbe equivalente:

var requiredFlags = new List<BindingFlags>(); 
requiredFlags.Add(BindingFlags.Public); 
requiredFlags.Add(BindingFlags.Static); 
typeof (A).GetFields(requiredFlags); 

Ora che non compilare come GetFields non prevede un tale sovraccarico, ma il significato sarebbe la stessa di quella del vostro codice.

Per riassumere le cose (TL; DR):

bit a bit e non ha nulla a che fare con booleano AND
OR bit per bit non ha nulla a che fare con booleano OR

+1

che ** in seguito ** verrà utilizzato con l'operatore '&' come 'if (userArgument & BindingFlags.Public) {/ * add a return value * /}' – Default

2

enum bandiera è in uso rappresentare un insieme di condizioni booleane.

Nell'esempio, ciascuna condizione booleana deve essere soddisfatta per il campo corrispondente da restituire.

I flag di enunciati sono semplicemente valori interi che obbediscono alle solite regole binarie per anding e oring, quindi per impostare più bit è necessario OR insieme ai valori che rappresentano quei bit.

Una volta fatto, si dispone di un flag enum con i bit appropriati impostati.

Il problema che si sta avendo è perché si confondono due concetti diversi: il modo in cui si costruisce l'insieme di condizioni booleane per un enumerato di bandiera è un concetto. Il modo in cui viene usato l'enum di bandiera (o ciò che rappresenta) è un concetto diverso.

Il primo utilizza OR per costruire l'insieme di condizioni booleane. Quest'ultimo indica che ogni bit rappresenta una condizione booleana che deve essere soddisfatta.

1

Gli implementatori di GetFields() hanno scelto interpretare la combinazione di vari flag ORed nel significato di una combinazione AND dei criteri selezionati.

Il che ha senso in quanto è sempre possibile eliminare un criterio se non si desidera il filtro aggiuntivo.

Problemi correlati