2010-08-11 65 views
14

我有一个Flags属性的枚举。获得枚举标志所有位的最佳方法?

我的问题是,我想获得所有选项的整数位掩码,而无需手动合并所有位。 我想这样做来比较一些其他的int领域,我想保护以防万一未来的开发人员更多的位选项的枚举。

另一件事是在我的枚举标志位将所有手动分配的,所以我不能简单地得到下一个值和减去1

回答

16

如果我明白你的要求正确这应该为你工作:

Enum.GetValues(typeof(Enum)).Cast<int>().Sum(); 
+0

+1,很干净。 – 2010-08-11 22:00:33

+4

只有在定义类型中不存在重复时才有效,这通常与同义词或预先组合的常见组合有关。 – 2010-08-11 22:03:39

+0

这绝对是最干净的解决方案,你也可以直接得到返回的数组,并执行任何其他想要的操作,如ORing而不是求和。 – Winforms 2010-08-11 22:05:06

6

看一看我的Unconstrained Melody项目,该项目确实邪恶的东西,让漂亮的功能将建立在约束枚举和委托的通用方法上。

在这种情况下,我想你想打电话给Flags.GetUsedBits<YourEnumType>()

如果你不介意使用额外的(非常小的)库,我想认为Unconstrained Melody在处理标志时会使生活更美好。如果您有任何功能请求,我很乐意看看:)

+0

非常有趣的项目,感谢您的洞察力。 – Winforms 2010-08-11 21:50:44

+0

我会接受这个答案,除非有人本能地提出某些东西。 – Winforms 2010-08-11 21:50:59

+0

我认为反射也可以在这里工作 – Winforms 2010-08-11 21:51:54

6
// uses a ulong to handle all possible underlying types without error 
var allFlags = Enum.GetValues(typeof(YourEnumType)) 
        .Cast<YourEnumType>() 
        .Aggregate((YourEnumType)0, (a, x) => a | x, a => (ulong)a); 
+0

我不能+1这个,因为它是如此接近我在输入“答案添加”消息时出现的内容。它在长枚举上失败,因此可能将Cast转换为Cast ? – 2010-08-11 22:07:00

+0

@Jon:固定。现在将聚合值输入为“ulong”,以便它可以处理所有可能的基础类型。 (我已经投了它,而不是把它作为'YourEnumType',因为OP要求一个* integer *位掩码。) – LukeH 2010-08-11 22:41:41

0

这里有一个办法做到这一点,使用的想法从乔恩斯基特和Marc Gravell写的generic operators

void Main() 
{ 
    Console.WriteLine(CombineAllFlags<MyEnum>()); // Prints "Foo, Bar, Baz" 
} 

[Flags] 
public enum MyEnum 
{ 
    Foo = 1, 
    Bar = 2, 
    Baz = 4 
} 

public static TEnum CombineAllFlags<TEnum>() 
{ 
    TEnum[] values = (TEnum[])Enum.GetValues(typeof(TEnum)); 
    TEnum tmp = default(TEnum); 
    foreach (TEnum v in values) 
    { 
     tmp = EnumHelper<TEnum>.Or(tmp, v); 
    } 
    return tmp; 
} 

static class EnumHelper<T> 
{ 
    private static Func<T, T, T> _orOperator = MakeOrOperator(); 

    private static Func<T, T, T> MakeOrOperator() 
    { 
     Type underlyingType = Enum.GetUnderlyingType(typeof(T)); 
     ParameterExpression xParam = Expression.Parameter(typeof(T), "x"); 
     ParameterExpression yParam = Expression.Parameter(typeof(T), "y"); 
     var expr = 
      Expression.Lambda<Func<T, T, T>>(
       Expression.Convert(
        Expression.Or(
         Expression.Convert(xParam, underlyingType), 
         Expression.Convert(yParam, underlyingType)), 
        typeof(T)), 
       xParam, 
       yParam); 
     return expr.Compile(); 
    } 

    public static T Or(T x, T y) 
    { 
     return _orOperator(x, y); 
    } 
} 

此代码动态创建,结合枚举值与作业者的委托

3

类似的原油,但类似的东西?

[Flags] 
enum SomeFlags 
{ 
    Flag1 = 1, 
    Flag2 = 2, 
    Flag3 = 4, 
    Flag4 = 16, 
    Flag5 = 32, 
    Flag6 = 64 
} 

static void Main(string[] args) 
{ 
    SomeFlags flags = 0; 

    SomeFlags[] values = (SomeFlags[])Enum.GetValues(typeof(SomeFlags)); 
    Array.ForEach<SomeFlags>(values, delegate(SomeFlags v) { flags |= v; }); 

    int bitMask = Convert.ToInt32(flags); 
}