2014-08-31 46 views
1

假設我有以下幾點:確定是否有任何標誌設置超過一定值

[Flags] 
public enum Options : long 
{ 
    None = 0, 

    Flag1 = 0x00000001, 
    Flag2 = 0x00000002, 
    Flag3 = 0x00000004, 
    Flag4 = 0x00000008, 
    Flag5 = 0x00000010, 
    // ... 
    FlagV = 0x10000000000, 
    FlagW = 0x20000000000, 
    FlagX = 0x40000000000, 
    FlagY = 0x80000000000, 
    FlagZ = 0x100000000000 
} 

目前,以確定是否設置一個標誌,我這樣做:

(myOptions & (long)Options.Flag1) == (long)Options.Flag1 

怎麼辦我確定是否設置了高於FlagV的ANY標誌(例如FlagW,FlagX等)並檢索其值(例如,如果設置了FlagW,FlagX和FlagZ,我想檢索FlagW的值)?換句話說,有沒有這樣一個另類:

if ((myOptions & (long)Options.FlagW) == (long)Options.FlagW) 
    return (long)Options.FlagW; 
else if ((myOptions & (long)Options.FlagX) == (long)Options.FlagX) 
    return (long)Options.FlagX; 
else if ((myOptions & (long)Options.FlagY) == (long)Options.FlagY) 
    return (long)Options.FlagY; 
// etc. 
+1

要檢查*標誌的任何*設置,使用'myOptions = 0'!爲了檢索它的值,只需將它與標誌本身進行按位與('&')即可。 – 2014-08-31 18:08:42

+0

對不起。編輯我的問題更清晰。基本上,我試圖確定是否設置了FlagV上的任何一個標誌,如果有的話,該標誌是什麼。 – arao6 2014-08-31 18:15:49

+0

@ arao6您的最後一段代碼與'return myOptions;'等價。 – 2014-08-31 18:18:37

回答

3

您可以通過所有選項值迭代。

var currentVal = Options.FlagV | Options.FlagW; 
    foreach (Options enumVal in Enum.GetValues(typeof(Options))) 
     if (enumVal > Options.FlagV && (enumVal & currentVal) == enumVal) 
       //Do stuff 
2

這將使你在myOptions設置標誌的列表:

var flags = Enum.GetValues(typeof(Options)) 
       .Where(f => myOptions.HasFlag(f)) 
       .ToList(); 

編輯:它看起來像你的myOptions實際上是一個長期的,否則你的代碼就不會因爲編譯您不能將&應用於枚舉和long。因此,嘗試這個:

var enumVal = (Options)myOption; 
var flags = Enum.GetValues(typeof(Options)) 
       .Where(f => enumVal.HasFlag(f)) 
       .ToList(); 
+0

我希望我可以接受多個答案:)你的方法也可以。 – arao6 2014-08-31 18:28:32

1

首先,你可能要重新考慮導致你超過32個標誌設計,這聽起來在自己的權利麻煩。

除此之外,認爲你只是在做位運算,所以像下面這樣既高效(編譯爲一對夫婦的指令),並且易於維護:

public enum Options : long 
{ 
    FlagA = 0x00000001, 
    // ... 
    FlagZ = 0x80000000, 
    // ... 
    HighFlags = 0xffff0000, 
    LowFlags = 0x0000ffff 
} 

然後你可以檢查任何HighFlags通過做(options & Options.HighFlags) != 0並且只得到HighFlagsoptions & Options.HighFlags

如果您不能修改枚舉,或不想依靠特定的值,你也可以or值一起在運行時:

public static class OptionsHelper 
{ 
    private readonly static Options HighFlags = Options.FlagM 
     | Options.FlagN 
     // ... 
     | Options.FlagZ; 

    public static bool HasHighFlags(this Options opt) 
    { 
     return (opt & HighFlags) != 0; 
    } 

    public static Options GetHighFlags(this Options opt) 
    { 
     return (opt & HighFlags); 
    } 

    public static IEnumerable<Options> GetSetHighFlags(this Options opt) 
    { 
     var highFlags = GetHighFlags(opt); 

     if (highFlags != 0) 
     { 
      for (ulong cFlag = 1; cFlag != 0; cFlag <<= 1) 
      { 
       if ((highFlags & cFlag) != 0) 
       { 
        yield return (Options)cFlag; 
       } 
      } 
     } 
    } 
} 

用作擴展方法(options.HasHighFlags())或options.GetSetHighFlags().First()

+0

Downvoter,關心評論? – Mitch 2014-08-31 18:36:34

+0

當然:它不回答這個問題。它只會告訴你是否設置了任何高位標誌,但不是這些標誌中的一個的值,問題也特別要求這樣做。 – hvd 2014-08-31 18:38:53

+0

@ hvd,注意。固定。 – Mitch 2014-08-31 18:39:40

0

你可以簡單地做這樣的事情:

if (optons & 0xfe0000000000) // Typecasts will be needed 
    // One of those flags is set. 

另外請注意,.NET的新版本支持options.HasFlag()方法,它簡化了確定一個標誌是否被定義。

其實,我沒有測試,但你應該能夠做這樣的事情:

if (optons.HasFlag(0xfe0000000000)) // Typecasts will be needed 
    // One of those flags is set. 
相關問題