2011-05-20 25 views
5

我喜歡寫枚舉或整數通過選項來我的方法。在C#中是否有模式或方法來檢查(int 1,2,4,8,...)選項是否爲真或假。我認爲應該很容易通過二進制函數。有圖案或C#中的方法來檢查,如果一個(INT 1,2,4,8,...)選項是真的還是假

class Program 
{ 
    public enum Option 
    { 
     Option_A = 1, 
     Option_B = 2, 
     Option_C = 4, 
     Option_D = 8, 
    } 

    static void Main(string[] args) 
    { 
     int activeOption = 5; // Means I activeted the Option_A and Option_C 
     if (IsOption(activeOption, Option.Option_A)) { /*do work*/ } 
     if (IsOption(activeOption, Option.Option_B)) { /*do work*/ } 
     if (IsOption(activeOption, Option.Option_C)) { /*do work*/ } 
     if (IsOption(activeOption, Option.Option_D)) { /*do work*/ } 
    } 

    private static bool IsOption(int activeOption, Option option) 
    { 
     /*Evaluate if IsOption is true or false*/ 
     throw new NotImplementedException(); 
    } 
} 

編輯

我僅限我可以創建這樣的選擇多少?

+1

爲什麼使用int而不是Option? – 2011-05-20 09:22:59

+0

@Martinho如果您看代碼示例,則需要多個選項可供選擇。int比一組選項更具空間效率。 – 2011-05-20 09:25:33

+1

@Robin:一個選項枚舉與int類型一樣具有空間效率。猜猜爲什麼:它實際上是一個整數。 – 2011-05-20 09:27:24

回答

10

(或者,如果你喜歡,是位域),你應該添加一個FlagsAttribute到它:

[Flags] 
public enum Option 
{ 
    Option_A = 1, 
    Option_B = 2, 
    Option_C = 4, 
    Option_D = 8, 
} 

然後,檢查通常與按位和操作員完成。演員陣容也將需要,因爲您正在使用int變量。

if(((Option)activeOption & Option.Option_A) != Option.Option_A) //... 

如果你想封裝這個齷齪了,檢查出Smudge202's answer鏈接的文章。如果您運行的是.NET 4,則甚至不需要執行此操作:請檢查sehe's answer

但你確實應該嘗試使用直接Option類型的變量,並結合使用按位或操作的選項:

Option activeOption = Option.Option_A | Option.Option_C; 

使用這個方案當然限制了您可以創建的選項數。如果保持原樣,則只能創建32個不同的選項,因爲int(枚舉的默認基礎類型)只有32位。如果使用long你可以有64種不同的選擇:

[Flags] 
public enum Option : long 
{ 
    Option_A = 1, 
    Option_B = 2, 
    Option_C = 4, 
    Option_D = 8, 
    // blah blah 
} 

但是,如果你需要的選項的任意數量,它可能是時候改變策略。你可以創建一個類似枚舉的自定義類型,但你可能會更好,只需要一個常規的非標誌枚舉和一個HashSet<Option>

public enum Option 
{ 
    Option_A = 1, // notice the sequential values now 
    Option_B = 2, 
    Option_C = 3, 
    Option_D = 4, 
} 

HashSet<Option> options = new HashSet<Option> { Option.Option_A, Option.Option_C }; 
if(options.Contains(Option.Option_A)) // ... 
+1

對於flags屬性爲+1。作爲答案的[我發佈的鏈接](http://www.codeproject.com/Articles/37921/Enums-Flags-and-Csharp-Oh-my-bad-pun.aspx)顯示了一種可用於擴展的方法測試枚舉成員時希望簡化您的答案,從而簡化代碼編寫。 – Smudge202 2011-05-20 09:31:39

+0

它將補充答案。此外,[C#4.0將補充它](http://stackoverflow.com/questions/6069869/is-there-a-pattern-or-a-method-in-c-to-check-if-an-int- 1-2-4-8-option-is-t/6070172#6070172) – sehe 2011-05-20 09:50:29

+0

@Martinho我是否限制了我可以創建的選項數量? – 2011-05-20 09:56:21

3

使用位並檢查在option位在activeOption設置。您還需要使這兩個參數相同的類型,從而使運營商將工作(你Option位掩碼檢查位反正):由於您枚舉包含標誌

private static bool IsOption(Option activeOption, Option option) 
{ 
    return (activeOption & option) == option; 
} 
+0

我得到一個錯誤 - >運算符'&'不能應用於'int'類型的操作數 – 2011-05-20 09:26:08

+0

@Dran Dane:您需要更改您的方法符號,以便兩個參數的類型相同。 – BoltClock 2011-05-20 09:26:55

+0

我是否限制了我可以創建的選項數量? – 2011-05-20 09:56:55

2

除了提到的FlagsAttribute,在C#中存在Enum.HasFlag Method

using System; 

[Flags] public enum DinnerItems { 
    None = 0, 
    Entree = 1, 
    Appetizer = 2, 
    Side = 4, 
    Dessert = 8, 
    Beverage = 16, 
    BarBeverage = 32 
} 

public class Example 
{ 
    public static void Main() 
    { 
     DinnerItems myOrder = DinnerItems.Appetizer | DinnerItems.Entree | 
          DinnerItems.Beverage | DinnerItems.Dessert; 
     DinnerItems flagValue = DinnerItems.Entree | DinnerItems.Beverage; 
     Console.WriteLine("{0} includes {1}: {2}", 
         myOrder, flagValue, myOrder.HasFlag(flagValue)); 
    } 
} 
// The example displays the following output: 
// Entree, Appetizer, Dessert, Beverage includes Entree, Beverage: True 
1

如果您使用的是.NET 4.0中,您可以使用HasFlag

static void Main(string[] args) 
{ 
    Option activeOption = (Option)5; // Means I activeted the Option_A and Option_C 
    if (activeOption.HasFlag(Option.Option_A)) { /*do work*/ } 
    if (activeOption.HasFlag(Option.Option_B)) { /*do work*/ } 
    if (activeOption.HasFlag(Option.Option_C)) { /*do work*/ } 
    if (activeOption.HasFlag(Option.Option_D)) { /*do work*/ } 
} 
相關問題