2012-11-19 76 views
5

我已經創建了一個擴展方法等..檢查是否完全只是這些標誌在枚舉集

public static bool AllFlagsSet<T>(this T input, params T[] values) where T : struct, IConvertible 
{ 
    bool allSet = true; 
    int enumVal = input.ToInt32(null); 

    foreach (T itm in values) 
    { 
     int val = itm.ToInt32(null); 
     if (!((enumVal & val) == val)) 
     { 
      allSet = false; 
      break; 
     } 
    } 

    return allSet; 
} 

這爲我所需要的目的的偉大工程,但是我現在有一個要求,以創建具有的方法相同的簽名檢查是否只有這些值已被設置。

基本上是這樣的。

public static bool OnlyTheseFlagsSet<T>(this T input, params T[] values) where T : struct, IConvertible 
{ 
} 

我能想到這樣做的唯一方法是讓它們設置所有可用的枚舉值檢查和確認僅供兩人一直。

是否有另一種方法來解決這個問題,使用某種按位操作?

+0

這是一門功課?爲什麼T約束一個結構而不是枚舉? – LightStriker

+0

哈哈,那真是令人尷尬。不,只是沒有對位操作的牢固掌握......這是一個真正的需求 –

+0

試着將它約束到Enum並看看會發生什麼。 ; -p –

回答

5

對所有需要的標誌執行「或」並與輸入進行比較 - 應該相等。類似下面,用正確的循環計算左側值:

var onlyTheseFlagsSet = (value[0] | value[1]) == input; 
0

我缺少的東西還是會不只是和PARAMS T []值和檢查,如果輸入等於結果?
如果你只想要那些標誌而沒有其他標誌,輸入應該等於那些標誌的總和。

+1

因爲'+'可能會很危險,因爲即使對於標誌類型,Enum值也不必互相排斥 - 需要使用或'|'來正確合併標誌。 –

1

這將翻轉每個輸入值的位。如果只設置了這些值,則結果值將爲零。否則,如果該值未在input中設置,則會將位翻轉爲1,這將使值不爲零。

public static bool OnlyTheseFlagsSet<T>(this T input, params T[] values) where T : struct, IConvertible 
{ 
    int enumVal = input.ToInt32(null); 

    foreach (T itm in values) 
    { 
     int val = itm.ToInt32(null); 
     enumVal = enumVal^val;     
    } 

    return (enumVal == 0); 
} 
+1

+1。我喜歡'''方法,但這個也很有趣。附註 - 請避免使用「itm」而不是「item」。 –

+0

我更喜歡'|'方法。同意變量名稱,我只保留原作者的風格。 –

+0

備註:剛纔注意到 - 你的代碼依賴於值互斥......即使對於標記爲標誌的Enum值,也不是必須的。 –

0

假設您可以將輸入轉化爲一個枚舉:

foreach(MyFlags flag in values) 
    if (!input.HasFlag(flag)) 
     return false; 

return true; 

是的,我很懶這樣。

+0

我認爲OP還希望確保其他標誌未設置...等待OP的評論... –

2

排他性要求意味着

input = values[0] | values[1] | ... | values[values.Length - 1]

所以,這裏是你實現:

return input.ToInt32(null) == values.Aggregate(0, 
     (total, next) => total | next.ToInt32(null)); 
+0

+1。 '.ToInt32(null)'看起來很奇怪,但仍然有效! –