给出以下标志,
[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;
}
我看不出问题所在。
答案 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;
}