2012-03-28 19 views
36

Ejemplo:¿Por qué uno usaría el operador | = en un valor booleano en C#?

Encontramos que este es un código escrito por un proveedor y estamos tratando de descubrir por qué lo harían.

bool tmp = false; 

if (somecase) 
    tmp = true; 

if (someOtherCase) 
    tmp |= true; 
+17

¿El lado derecho es realmente un "verdadero" constante? Usar '| =' en bools es perfectamente razonable, usar '| = true' rara vez lo es. – CodesInChaos

+3

Sabe que incluso [msdn] (http://msdn.microsoft.com/en-us/library/h5f1zzaw.aspx) enumera un booleano y los operadores '| =' en su ejemplo ... –

Respuesta

68

Sin ninguna buena razón en absoluto. Un valor booleano |= true siempre será true. Esto es alguien tratando de ser elegante, u olvidando la lógica booleana =)

Cambie a tmp = true;.

+0

Gracias después algunos programas de prueba llegué a esa conclusión ... razón por la cual pregunté ... no puedo estar a salvo. – carny666

+8

@ code4life: 'falso | true' sigue siendo "verdadero" ... ¿Olvidas también tu lógica booleana? –

+1

@ code4life: OK, ¿y si fuera? Entonces, ¿cuál es su estado después de "tmp | = true;"? –

2

El resultado final será "Si cualquiera de los casos es cierto, el resultado será verdadero". Sin embargo, no hay ninguna razón por la que deba usar el operador, ya que el || en un if funcionaría igual de bien.

+2

Si 'someOtherCase' tiene efectos secundarios, necesitaría usar' | 'en lugar de' || 'para conservarlos. – phoog

7

interesante - que parece que se está haciendo el equivalente:

tmp = tmp | true; 

que siempre será establecido tmp en true.

16

Quizás uno de los literales booleanos solía ser una variable, y simplemente no pensaron cambiar el operador cuando cambiaron el operando. Obviamente, la lógica es equivalente.

Es más probable que pensaran que, en el segundo caso, quieren conservar el resultado de evaluar la primera condición "si". Por supuesto, eso es falso razonamiento.

una declaración equivalente más simple:

bool tmp = somecase | someOtherCase; 

EDITAR

Como notas pickypg, esta declaración podría ser confuso, ya que la mayoría de la gente no espera | con valores booleanos, y muchos no lo notará , o no piensa en las implicaciones de los efectos secundarios. La mejor manera de ser explícito (si de hecho hay efectos secundarios) sería la solución de minitech: simplemente cambie el |= al =.

O, si no hay efectos secundarios en la expresión someOtherCase, use la solución de Jakub Konecki: someCase || someOtherCase.

+0

Eso es lo que pensamos ... o tal vez un afortunado tipo-o. – carny666

+1

Sospecho que era el código original, pero incluso eso debería convertirse a 'bool tmp = somecase || someOtherCase; 'para permitir que el cortocircuito haga su trabajo. Si desea los efectos secundarios, es probable que esté destruyendo la legibilidad alineando el código, particularmente al asociar implícitamente los dos métodos que solo pueden asociarse libremente en ese punto (ya que el primero no impide que el segundo "falle"). "o lo que sea que' falso 'representa). – pickypg

+0

@pickypg Estoy de acuerdo en que alinear el código con '|' disminuye la legibilidad. También hay una gran posibilidad de que alguien "corrija" el '|' en '||' en algún momento. Ambos son verdaderos porque usar '|' con valores booleanos no es realmente C# idiomático. Me parece una pena, pero no hay mucho que hacer al respecto. – phoog

0

Esto es equivalente a

tmp = tmp | true; 

EDIT: que es igual a

tmp = true; 

estoy de acuerdo con el resto de los críticos aquí ...!

Más información here

7

foo |= true es una versión corta de foo = foo | true.

El código real puede reescribirse como

bool tmp = false; 
tmp |= someCase; 
tmp |= someOtherCase; 

O aún mejor, ya

someCase || someOtherCase 
+4

Pequeña objeción: si alguna otra causa tiene efectos secundarios, 'someCase | someOtherCase' los preservaría, mientras que 'someCase || someOtherCase' no lo haría. – phoog

+2

someCase | someOtherCase – phkahler

0

Su expresión utilizando el | = operador de asignación. Check MSDN

+0

Sí, miré y entendí que simplemente no tenía sentido dónde lo usaban en el código que tenía. – carny666

1

Un compilador inteligente podría evitar la asignación en este caso, aunque probablemente no lo haría ya que no debería provocar un cortocircuito en una operación de bit a bit. En cualquier caso, parece una micro-optimización. En realidad, sospecho que se trata de un patrón de retención que el autor usa para usar indicadores de bits (o el/ella no comprende cómo funciona). Sería mejor como:

bool tmp = somecase || someOthercase; 

(en línea y luego el temporal si lo utiliza solamente una vez)

Tenga en cuenta que, al usar banderas, sí tiene sentido.

#define CONDITION_ONE 0x01 
#define CONDITION_TWO 0x02 

int temp = 0; 
if (somecase) { 
    temp = CONDITION_ONE; 
} 

if (someOthercase) { 
    temp |= CONDITION_TWO; 
} 
+0

Esto no conserva los efectos secundarios de 'someOtherCase', si hay alguno que conservar. – phoog

+0

@phoog - eso es cierto. si los casos son funciones o contienen declaraciones, entonces el uso de la evaluación diferida no sería el mismo y no deberían combinarse. – tvanfosson

+0

Puede combinarlos con el operador '|'. – phoog

0

para Bools no tanto

embargo

para bitflags Esto puede permitir código como este:

int flags=0; 
flags|=READ; 
//flags|=UPDATE; 
foo(arg,flags); 

esto permite algunas banderas para ser comentados fácilmente (y hace las banderas usadas un poco OMI más legible)

4

Al igual que los otros operadores op = x |= y es equivalente (excepto efectos secundarios de evaluación múltiple) a x = x | y. Esta es una manera concisa de escribir if (!x) x = y; o if (y) x = true;.

Sin embargo, no tiene sentido tener constante en el lado derecho.

  • x |= true se escribe más directa como x = true
  • x |= false deja x sin cambios.

por qué harían esto.

Algunas posibles explicaciones son:

  • Es un error tipográfico: Se referían a escribir en lugar de tmp = true;tmp |= true;, pero nunca se dieron cuenta que debido a que su programa pasó a funcionar como se espera.
  • El RHS era originalmente una variable, que se reemplazó con la constante true sin cambiar el código.
  • tmp era originalmente un bitfield (para el cual |= tiene más sentido), que luego se redujo a un solo bit.
Cuestiones relacionadas