2011-03-29 40 views
3

我有一个看起来像这样的枚举:Bitmask'ed诠释至ENUM []或INT []? C#

enum foo{ 
a=0, 
b=1, 
c=2, 
d=4 
} 

构建标志/位掩码是好的,但有可能像做

int i = 3; 
var bar = Enum.Split(foo,i); 

的东西得到的像

bar = foo[]{a, b,c}; 

感谢。

回答

7

请尝试以下

public static IEnumerable<T> Split<T>(int value) { 
    foreach (object cur in Enum.GetValues(typeof(T))) { 
    var number = (int)(object)(T)cur; 
    if (0 != (number & value)) { 
     yield return (T)cur; 
    } 
    } 
} 

有了这个,你现在可以写

int i = 3; 
IEnumerable<foo> e = Split<foo>(i); 

注:enum值从int(默认设置)获得这只作品。它也不是完全类型安全的,因为T不能仅限于enum的值(尽管如此,没有关系)

+0

喜欢的话贾里德而言,我惊讶心不是一个内置的操作,解决了这个开箱。 – maxp 2011-03-29 16:16:35

+0

为什么我们不能添加'where T:Enum'? – 2011-03-29 16:28:01

+0

@Vash C#不允许通用参数被约束为'enum'值。 – JaredPar 2011-03-29 16:35:20

3

您可以使用枚举的FlagsAttribute并获得大量的功能免费(不需要在位级别工作)。

MSDN描述作为属性:

表示枚举可以作为一个位域进行处理;也就是一组标志。

+0

以及如何斯普利特的组合值到一个数组? – 2011-03-29 16:43:36

+0

@Henk - 这不,但是,使用这些可避免的原因,希望拆分合并值。 – Oded 2011-03-29 18:02:47

2

试试这个:

TEnum[] EnumSplit<TEnum>(int mask) 
{ 
    List<TEnum> values = new List<TEnum>(); 
    foreach(int enumValue in Enum.GetValues(typeof(TEnum))) 
    { 
     if(mask & enumValue == enumValue) 
      values.Add((TEnum)enumValue); 
    } 
    return values.ToArray(); 
} 

这样称呼它:

var bar = EnumSplit<foo>(i); 

最好,你想改变它返回的IEnumerable<TEnum>代替TEnum[]

1

你可以用它从拉动值的方法做到这一点Enum传递:

public static T[] EnumSplit<T>(int value) where T : struct 
{ 
    // Simplified as Enum.GetValues will complain if T is not an enum 
    // However, you should add a check to make sure T implements FlagAttribute 
    return (from vv in Enum.GetValues(typeof(T)) 
      where ((int)vv & value) != 0 
      select (T)vv).ToArray();; 
} 
0
var flags = Enum.GetValues(typeof (/* YourEnumType */)) 
        .Cast</* YourEnumType */>() 
        .Select(v => enumValue.HasFlag(v)) 
        .ToArray(); 
+0

我不相信会编译,因为C#无法知道'T'实现'HasFlag'。 – user7116 2011-03-29 16:22:05

+0

@sixlettervariables,我不相信,谢谢 – Snowbear 2011-03-29 16:25:11