Учитывая следующие флаги,
[Flags]
public enum Operations
{
add = 1,
subtract = 2,
multiply = 4,
divide = 8,
eval = 16,
}
Как я мог реализовать ЕСЛИ условие выполнить каждую операцию? В моей попытке первое условие верно для, добавляют, оценка, которая корректна. Однако первое условие также верно для, вычитают, оценка, которая является неправильной.
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;
}
Я не вижу, какова проблема.
Измените внутренние &
на |
:
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 in binary is 00001
16 in binary is 10000
00001
& 10000
--------
00000
Итак, скажем, у нас есть Subtract (2) как операция
2 in binary is 00010
previous result is 00000
00010
& 00000
--------
00000
Поскольку предыдущий результат - 00000
что угодно И Буду с ней нулю. Таким образом, ваше условие всегда будет оцениваться как true
, поскольку 0 == 0
.
Если мы просто переключим это на 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
( все еще ложно! )
Итак, на самом деле вам нужно:
((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
Это явно не читается, поэтому вам следует выбрать извлечение в метод (как предлагается). Но все же важно понять, почему ваше условие неверно.
Попробуйте следующее:
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;
}
Причина сбоя операции в том, что у вас неправильное выражение. (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;
}