2010-04-02 186 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

這顯然不是可讀的,所以你應該選擇提取到本一種方法(如建議)。但它仍然很重要明白爲什麼你的情況是不正確的。