C# 枚举标志比较

发布于 2024-08-27 03:35:07 字数 839 浏览 4 评论 0原文

给定以下标志,

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

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

我看不出问题是什么。

Given the following flags,

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

How could I implement an IF condition to perform each operation? In my attempt, the first condition is true for add, eval, which is correct. However the first condition is also true for subtract, eval, which is incorrect.

        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;
    }

I cannot see what the problem is.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

旧时浪漫 2024-09-03 03:35:07

将内部 & 更改为 |

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

Change your inner & to |:

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

This is equivalent to:

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

which might be more readable. You might also want to consider an Extension like this:

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

then you can do this:

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

which might be even more readable. Finally you could create this extension for even more fun:

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

Then your expression could turn into:

if(operation.HasAllFlags(Operations.add, Operations.eval))
只有影子陪我不离不弃 2024-09-03 03:35:07

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

如果您使用标志,那么理解按位数学非常重要。在您的情况下,您有以下内容(对于第一个条件):

1 in binary is  00001
16 in binary is 10000

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

因此,假设我们将减去(2)作为操作

2 in binary is     00010
previous result is 00000

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

因为之前的结果是00000任何AND' d 将为零。因此,由于 0 == 0,您的条件将始终评估为 true

如果我们只是将其切换为 OR,那么我们将得到以下结果:

1 in binary is  00001
16 in binary is 10000

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

现在,假设我们将 Add (1) 作为操作

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仍然是 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

这显然不可读,因此您应该选择将其提取到方法中(按照建议)。但了解为什么您的情况不正确仍然很重要。

Wow, I can't believe all of the wrong answers..

It's important to understand bitwise math if you're working with flags. In your case, you have the following (for the first condition):

1 in binary is  00001
16 in binary is 10000

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

So, say we have Subtract (2) as the operation

2 in binary is     00010
previous result is 00000

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

Since the previous result is 00000 anything AND'd with it will be zero. So your condition will always evaluate to true since 0 == 0.

If we just switch this to OR, then we have the following:

1 in binary is  00001
16 in binary is 10000

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

Now, say we have Add (1) as the operation

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

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

So, 1 & 17 => 1 and thus your final condition is (1 & ( 1 | 16 ) ) == ( 1 | 16 ) => 1 & 17 == 17 => 1 == 17 => false (still false!)

So what you actually want is:

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

This becomes ((1 | 1 | 16 ) & ( 1 | 16 )) == ( 1 | 16 ) => ( 17 & 17 ) == 17 => 17 == 17 == true

This is obviously not readable, so you should opt for extracting this into a method (as suggested). But it's still important to understand why your condition is incorrect.

千秋岁 2024-09-03 03:35:07

重复:

请参阅如何在 C# 中比较标志?

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

但是,请参阅 是什么让 Enum.HasFlag 如此缓慢? 如果性能是一个问题。

Duplicate:

See How to Compare Flags in C#?

C# 4 introduces the Enum.HasFlags() method.

However, see What is it that makes Enum.HasFlag so slow? if perfomance is an issue.

北陌 2024-09-03 03:35:07

你的操作失败的原因是你的表达式错误。 (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;
}

The reason your operation is failing is because you have the wrong expression. (Operations.add & Operations.eval) is always zero. Left and right side of your first comparison are both always zero. Try this instead - I suspect it's what you were after:

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;
}
向地狱狂奔 2024-09-03 03:35:07

试试这个:

   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;
}

Try this:

   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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文