2010-04-02 13 views
5

Dadas las siguientes banderas,Banderas C# Enum comparación

[Flags] 
    public enum Operations 
    { 
     add = 1, 
     subtract = 2, 
     multiply = 4, 
     divide = 8, 
     eval = 16, 
    } 

¿Cómo podría implementar una condición IF para realizar cada operación? En mi intento, la primera condición es verdadera para add, eval, que es correcta. Sin embargo, la primera condición también es verdadera para restar, eval, que es incorrecta.

 public double Evaluate(double input) 
    { 
     if ((operation & (Operations.add & Operations.eval)) == (Operations.add & Operations.eval)) 
      currentResult += input; 
     else if ((operation & (Operations.subtract & Operations.eval)) == (Operations.subtract & Operations.eval)) 
      currentResult -= input; 
     else 
      currentResult = input; 

     operation = null; 

     return currentResult; 
    } 

no veo cuál es el problema.

+1

¿Soy yo el que piensa que [Flags] para la operación que se muestra no es correcto? Estoy luchando por pensar en una muestra del mundo real donde tendría las banderas en las operaciones matemáticas que se muestran ... – Sunny

+0

Estoy de acuerdo Sunny. Se suponía que las banderas representaban estados en una calculadora. No estoy seguro de por qué lo hice de esta manera. En retrospectiva, no lo haría de esta manera ahora. –

+0

Posible duplicado de [Cómo comparar banderas en C#?] (Http://stackoverflow.com/questions/40211/how-to-compare-flags-in-c) –

Respuesta

23

Cambiar la interna & a |:

if ((operation & (Operations.add | Operations.eval)) == (Operations.add | Operations.eval)) 

Esto es equivalente a:

if(((operation & Operations.add)==Operations.add) && 
    ((operation & Operations.eval)==Operations.eval)) 

que podría ser más fácil de leer. También puede ser que desee considerar una extensión de esta manera:

public static bool HasFlag(this Operations op, Operations checkflag) 
{ 
    return (op & checkflag)==checkflag; 
} 

entonces usted puede hacer esto:

if(operation.HasFlag(Operations.add) && Operations.HasFlag(Operations.eval)) 

que podrían ser aún más fácil de leer. Por último se podría crear esta extensión para divertirse aún más:

public static bool HasAllFlags(this Operations op, params Operations[] checkflags) 
{ 
    foreach(Operations checkflag in checkflags) 
    { 
     if((op & checkflag)!=checkflag) 
      return false; 
    } 
    return true; 
} 

Luego, su expresión se puede convertir en:

if(operation.HasAllFlags(Operations.add, Operations.eval)) 
+0

+1 ¡Gran respuesta! –

+0

La sugerencia inicial es incorrecta; la solución final es correcta;) –

+0

A menos que encuentre esto ilegible, necesita 'HasAllFlags' por separado, porque puede usar' HasFlag' como: 'if (operation.HasFlag (Operations.add | Operations.eval))'. – weston

1

La razón de su operación está fallando es porque tiene la expresión equivocada. (Operations.add & Operations.eval) es siempre cero. El lado izquierdo y derecho de su primera comparación son ambos siempre cero. Prueba este lugar - Sospecho que es lo que buscábamos:

public double Evaluate(double input) 
{ 
    if ((operation & (Operations.add | Operations.eval)) == (Operations.add | Operations.eval)) 
     currentResult += input; 
    else if ((operation & (Operations.subtract | Operations.eval)) == (Operations.subtract | Operations.eval)) 
     currentResult -= input; 
    else 
     currentResult = input; 

    operation = null; 

    return currentResult; 
} 
1

Prueba esto:

public double Evaluate(double input) 
{ 
    if ((operation & (Operations.add | Operations.eval)) == (Operations.add | Operations.eval)) 
     currentResult += input; 
    else if ((operation & (Operations.subtract | Operations.eval)) == (Operations.subtract | Operations.eval)) 
     currentResult -= input; 
    else 
     currentResult = input; 

    operation = null; 

    return currentResult; 
} 
11

Wow, no puedo creer todas las respuestas incorrectas ..

Es importante Comprenda las operaciones en bits si está trabajando con banderas. En su caso, usted tiene los siguientes (para la primera condición):

1 in binary is 00001 
16 in binary is 10000 

    00001 
& 10000 
-------- 
    00000 

Por lo tanto, digamos que tenemos Restar (2) como el operation

2 in binary is  00010 
previous result is 00000 

    00010 
& 00000 
-------- 
    00000 

Dado que el resultado anterior es 00000 nada Y' d con ella será cero. Entonces su condición siempre evaluará a true desde 0 == 0.

Si simplemente interruptor de esto a O, entonces tenemos lo siguiente:

1 in binary is 00001 
16 in binary is 10000 

    00001 
| 10000 
-------- 
    10001 (17) 

Ahora, digamos que tenemos Add (1) como el operation

1 in binary is  00001 
previous result is 10001 (17) 

    00001 
& 10001 
-------- 
    00001 

Así, 1 & 17 => 1 y por lo tanto su última la condición es (1 & (1 | 16)) == (1 | 16) =>1 & 17 == 17 =>1 == 17 =>false (¡aún falso!)

Así que lo que realmente quiere decir:

((operation | Operations.add | Operations.eval) & (Operations.add | Operations.eval)) == (Operations.add | Operations.eval) 

esto se convierte en ((1 | 1 | 16) & (1 | 16)) == (1 | 16) =>(17 & 17) == 17 =>17 == 17 == true

Esto obviamente no es legible, por lo que debe optar por la extracción de esto en un método (como se sugiere). Pero todavía es importante saber por qué su condición es incorrecta.