2011-09-19 83 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); 
}