2011-09-19 133 views
7

假設你有 enum MyEnum {A = 0, B = 1, C = 2, D = 4, E = 8, F = 16};C#:檢查一組枚舉值的最佳方法?

在某些時候你必須將檢查MyEnum的實例,如果是C,d,或F

bool IsCDF(MyEnum enumValue) 
{ 
    return //something slick 
} 

我記得有一些返回true功能真正光滑的方法來做位移和預製這種操作,比一堆三元的if語句讀得更好,但對於我的生活,我不記得它是什麼。

有人知道嗎?

+0

http://stackoverflow.com/questions/93744/most-common-c-bitwise-operations/417217#417217 –

回答

15

如果你讓一個[國旗]枚舉,您可以分配不同的位值(1,2,4,8,16 ...),以每個枚舉值。然後,您可以使用按位操作來確定值是否是一組可能值中的一個。

所以,看它是否是C,d,或F:

bool IsCDF(MyEnum enumValue) 
{ 
    return((enumValue & (MyEnum.C | MyEnum.D | MyEnum.F)) != 0); 
} 

注意,這不會爲0值工作(在你的榜樣, 'A'),你必須是小心所有的枚舉值都解析爲唯一的位值(即非0的冪)。

這種方法的優點是:

  • 它通常會採取單一的CPU指令來執行,而做了三分開「如果」檢查將採取3點或更多的指令(​​具體取決於你的目標平臺)。
  • 您可以將要測試的值作爲枚舉值(單個整數)傳遞,而不需要使用枚舉值列表。
  • 你可以做很多其他有用的事情,按位操作,這將是笨重和慢的普通數值/比較方法。
+0

是的,我墊和紙類似的東西。我想用BCL的ConnectionState這可悲的是有ConnectionState。關閉= 0 - 我可以把所有東西都提高到2的強度,但是我們現在要離開'光滑'的範圍。 –

+0

雖然,如果我檢查的列表不包含0,那麼它總是應該評估爲false ... –

+0

是的,我遲了2年 - 但我會反對這個建議,因爲它在長期跑。不太可讀,不是很乾淨。 – FrankB

0
return (enumValue & MyEnum.C == MyEnum.C) 
     || (enumValue & MyEnum.D == MyEnum.D) 
     || (enumValue & MyEnum.F == MyEnum.F); 
+1

我不認爲OP有興趣檢查它的這種方式。 –

+0

是的,這仍然基本上是如果語句,只是不是真/假 –

5

我想可能使用Unconstrained Melody爲保持整潔的事情的一種方式:

if (value.HasAny(MyEnum.C | MyEnum.D | MyEnum.E)) 
{ 
    ... 
} 

我可能會提取「C,d或E」位到一個名爲不變 - 可能在枚舉本身,如果它有含義:

1

也許這個擴展類是您有用:

public static class Flags 
{ 
    /// <summary> 
    /// Checks if the type has any flag of value. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="type"></param> 
    /// <param name="value"></param> 
    /// <returns></returns> 
    public static bool HasAny<T>(this System.Enum type, T value) 
    { 
     try 
     { 
      return (((int) (object) type & (int) (object) value) != 0); 
     } 
     catch 
     { 
      return false; 
     } 
    } 

    /// <summary> 
    /// Checks if the value contains the provided type. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="type"></param> 
    /// <param name="value"></param> 
    /// <returns></returns> 
    public static bool Has<T>(this System.Enum type, T value) 
    { 
     try 
     { 
      return (((int)(object)type & (int)(object)value) == (int)(object)value); 
     } 
     catch 
     { 
      return false; 
     } 
    } 

    /// <summary> 
    /// Checks if the value is only the provided type. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="type"></param> 
    /// <param name="value"></param> 
    /// <returns></returns> 
    public static bool Is<T>(this System.Enum type, T value) 
    { 
     try 
     { 
      return (int)(object)type == (int)(object)value; 
     } 
     catch 
     { 
      return false; 
     } 
    } 

    /// <summary> 
    /// Appends a value. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="type"></param> 
    /// <param name="value"></param> 
    /// <returns></returns> 
    public static T Add<T>(this System.Enum type, T value) 
    { 
     try 
     { 
      return (T)(object)(((int)(object)type | (int)(object)value)); 
     } 
     catch (Exception ex) 
     { 
      throw new ArgumentException(
       string.Format(
        "Could not append value from enumerated type '{0}'.", 
        typeof(T).Name 
        ), ex); 
     } 
    } 

    /// <summary> 
    /// Appends a value. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="type"></param> 
    /// <param name="value"></param> 
    /// <returns></returns> 
    public static void AddTo<T>(this System.Enum type, ref T value) 
    { 
     try 
     { 
      value = (T)(object)(((int)(object)type | (int)(object)value)); 
     } 
     catch (Exception ex) 
     { 
      throw new ArgumentException(
       string.Format(
        "Could not append value from enumerated type '{0}'.", 
        typeof(T).Name 
        ), ex); 
     } 
    } 

    /// <summary> 
    /// Removes the value. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="type"></param> 
    /// <param name="value"></param> 
    /// <returns></returns> 
    public static T Remove<T>(this System.Enum type, T value) 
    { 
     try 
     { 
      return (T)(object)(((int)(object)type & ~(int)(object)value)); 
     } 
     catch (Exception ex) 
     { 
      throw new ArgumentException(
       string.Format(
        "Could not remove value from enumerated type '{0}'.", 
        typeof(T).Name 
        ), ex); 
     } 
    } 

    /// <summary> 
    /// Removes the value. 
    /// </summary> 
    /// <typeparam name="T"></typeparam> 
    /// <param name="type"></param> 
    /// <param name="value"></param> 
    /// <returns></returns> 
    public static void RemoveFrom<T>(this System.Enum type, ref T value) 
    { 
     try 
     { 
      value = (T)(object)(((int)(object)type & ~(int)(object)value)); 
     } 
     catch (Exception ex) 
     { 
      throw new ArgumentException(
       string.Format(
        "Could not remove value from enumerated type '{0}'.", 
        typeof(T).Name 
        ), ex); 
     } 
    } 
} 
17
bool IsCDF(MyEnum enumValue) 
{ 
    return new[]{MyEnum.C, MyEnum.D, MyEnum.F}.Contains(enumValue); 
}