C#Enum标志比较

时间:2010-04-02 14:57:51

标签: c# enums

给出以下标志,

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

如何实现IF条件来执行每个操作?在我的尝试中,第一个条件适用于 add,eval ,这是正确的。然而,第一个条件也适用于减法,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;
    }

我看不出问题所在。

5 个答案:

答案 0 :(得分:24)

将您的内心&更改为|

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))

答案 1 :(得分:12)

哇,我无法相信所有错误的答案..

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

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,因此与它的任何AND将为零。因此,从true开始,您的情况将始终评估为0 == 0

如果我们只是将其切换为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

这显然是不可读的,因此您应该选择将其提取到方法中(如建议的那样)。但理解为什么你的病情不正确仍然很重要。

答案 2 :(得分:4)

重复:

请参阅How to Compare Flags in C#?

C#4引入了Enum.HasFlags()方法。

但是,如果性能问题,请参阅What is it that makes Enum.HasFlag so slow?

答案 3 :(得分: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;
}

答案 4 :(得分: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;
}