OR bit a bit per definire SqlBulkCopyOptions?

bitwise-or c# sqlbulkcopy

Domanda

Così ho chiesto ad uno dei miei sviluppatori senior di aiutarci a capire il problema relativo al campo Transaction e lui è venuto alla mia scrivania e ha usato un sovraccarico diverso su SqlBulkCopy e per il parametro SqlBulkCopyOptions ha fatto qualcosa di simile qui sotto:

SqlBulkCopyOptions options = (SqlBulkCopyOptions.FireTriggers | SqlBulkCopyOptions.CheckConstraints);

Funziona ora, ma non capisco cosa sia un bitwise or mezzo qui. Pensavo di averne capito qualcosa, non l'ho mai usato veramente, ma questo uso mi ha fatto grattarmi la testa. Sì, non ho chiesto al mio superiore di spiegarmelo .. Speravo che qualcuno potesse aiutarmi a capire cosa fa la dichiarazione. La maggior parte degli esempi o bit sulla rete sono con alcuni numeri, che ottengo (credo), ma questo?

Risposta accettata

Un enum può essere usato come flag se ha l'attributo [Flags] e ha valori enum indipendenti l'uno dall'altro:

La definizione di SqlBulkCopyOptions è qui: https://github.com/Microsoft/referencesource/blob/master/System.Data/System/Data/SqlClient/SqlBulkCopyOptions.cs

Ignora l'uso della sintassi bitshift. I valori effettivi sono:

Name              Hex  Dec  Pow 2   Binary
Default          =  0 =  0 =    0 = 00000000
KeepIdentity     =  1 =  1 =    1 = 00000001
CheckConstraints =  2 =  2 =    2 = 00000010
TableLock        =  4 =  4 =    3 = 00000100
KeepNulls        =  8 =  8 =    4 = 00001000
FireTriggers     = 10 = 16 =    5 = 00010000
UseInternalTxn   = 20 = 32 =    6 = 00100000

Osserva che ogni valore è la potenza successiva di 2, il che significa che in binario (ultima colonna) i loro bit sono completamente mutuamente esclusivi.

Ciò significa che è possibile combinarli in un modo che consente di vedere ogni valore impostato, ad esempio se si desidera KeepIdentity e TableLock , ovvero 0x01 con 0x04 . Usiamo l'operatore OR, ma su base per bit, che ci dà il comportamento che vogliamo:

In binario:

00000001
00000100 OR
--------
00000101

Osserva come ora il primo e il terzo bit sono 1 .

Quindi, ( KeepIdentity | TableLock == 5 ).

Questo approccio non funziona per i valori enum che non sono potenze di due, ad esempio se KeepIdentity ha un valore 1 e CheckConstraints ha un valore 2 ma TableLock ha un valore di 3 , quindi in binario sono:

00000001 KeepIdentity
00000010 CheckConstraints
00000011 TableLock

Osservare che analizzando i bit di 00000011 è impossibile determinare se questa è la combinazione di KeepIdentity e CheckConstraints o un singolo valore TableLock . Questo è il motivo per cui i valori di enumerazione delle bandiere devono essere: 1. Poteri di 2 e 2: si escludono a vicenda (con eccezioni per i valori di stenografia e combinazione).


Risposta popolare

Il principio è esattamente lo stesso con enum come lo è con i numeri, poiché il tipo sottostante di enum è sempre un tipo integrale. Se si osserva la dichiarazione di SqlBulkCopyOptions , si vedrà che i suoi membri hanno valori sottostanti che sono potenze di due in modo che possano essere combinati in questo modo.



Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow
Autorizzato sotto: CC-BY-SA with attribution
Non affiliato con Stack Overflow