2010-04-02 109 views
5

鉴于以下标志,C#枚举标志比较

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

我怎么能实现一个IF条件进行各项操作?在我的尝试中,第一个条件是加,eval,这是正确的。然而,第一个条件也是如此,减去,评估,这是不正确的。

 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

只是我认为[Flags]所显示的操作不正确?我正在努力想到一个真实的世界样本,我会在数学运算上显示标志...... – Sunny 2010-04-02 15:09:25

+0

我同意Sunny。这些标志应该代表一个计算器中的状态。我不知道为什么我这样做。回想起来,我现在不会这样做。 – 2011-09-28 06:50:05

+0

[如何在C#中比较标志?]可能重复(http://stackoverflow.com/questions/40211/how-to-compare-flags-in-c) – 2015-10-26 14:01:38

回答

23

改变内心&|

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

这相当于:

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

这可能是更具可读性。您可能还需要考虑这样的一个扩展:

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

,那么你可以这样做:

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

,这可能是更具有可读性。最后,你可以更有趣创建此扩展名:

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

那么你的表达可能变成:

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

+1很好的答案! – 2010-04-02 15:43:17

+0

最初的建议是错误的;最后的解决方案是正确的;) – 2010-04-02 15:45:01

+0

除非你觉得这是不可读的,你是否需要单独的'HasAllFlags',因为你可以像这样使用'HasFlag':'if(operation.HasFlag(Operations.add | Operations.eval))'。 – weston 2012-11-14 12:55:06

1

你的操作失败的原因是因为你有错误的表达。 (Operations.add & Operations.eval)总是零。你的第一个比较的左侧和右侧都是零。试试这个 - 我怀疑这就是你以后:

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

试试这个:

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

哇,我真不敢相信所有的错误答案..

很重要了解按位数学计算,如果你正在使用标志。你的情况,你有以下的(第一个条件):

1 in binary is 00001 
16 in binary is 10000 

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

所以,说我们有减(2)为operation

2 in binary is  00010 
previous result is 00000 

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

自上次结果为00000什么,”与它一起将是零。所以你的病情总是会从0 == 0开始计算到true

如果我们只是此开关OR,那么我们有以下几点:

1 in binary is 00001 
16 in binary is 10000 

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

现在,假设我们有最终Add (1)operation

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

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

所以,1 & 17 => 1从而条件是(1 & (1 | 16)) == (1 | 16) =>1 & 17 == 17 =>1 == 17 =>false仍然是假的!

所以,你真正想要的是:

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

这成为((1 | 1 | 16) & (1 | 16)) == (1 | 16) =>(17 & 17) == 17 =>17 == 17 == true

这显然不是可读的,所以你应该选择提取到本一种方法(如建议)。但它仍然很重要明白为什么你的情况是不正确的。