如何从枚举值中获取标志?

时间:2015-11-26 21:16:48

标签: c# enum-flags

尝试从枚举值中获取所有可能的标志数组,例如3到数组{1,2}。

我有一个扩展名

internal static MyEnum[] GetFlags(this MyEnum modKey)
{            
    string[] splitStr = modKey.ToString().Split(new string[1] { ", " }, StringSplitOptions.RemoveEmptyEntries);

    MyEnum[] flags = new MyEnum[splitStr.Length];
    for (int i = 0; i < splitStr.Length; i++)
    {
        flags[i] = (MyEnum)Enum.Parse(typeof(MyEnum), splitStr[i]);
    }
    return flags;
}

......但这个目的似乎有点浪费。这可以更有效地完成吗?

2 个答案:

答案 0 :(得分:3)

您只需将MyEnum的所有可能值过滤为modKey中的值:

internal static MyEnum[] GetFlags(this MyEnum modKey)
{
    return Enum.GetValues(typeof(MyEnum))
        .Cast<MyEnum>()
        .Where(v => modKey.HasFlag(v))
        .ToArray();
}

修改

根据下面的注释,如果指定了组合,该方法应仅返回组合,而不是所有标志集。

解决方案是循环遍历从最高标记开始的枚举中设置的所有标志。在每次迭代中,我们必须在结果中添加一个标志,并将其从迭代的枚举中删除,直到它为空:

internal static MyEnum[] GetFlags(this MyEnum modKey)
{
    List<MyEnum> result = new List<MyEnum>();

    while (modKey != 0)
    {
        var highestFlag = Enum.GetValues(typeof(MyEnum))
            .Cast<MyEnum>()
            .OrderByDescending(v => v)
            .FirstOrDefault(v => modKey.HasFlag(v));

        result.Add(highestFlag);
        modKey ^= highestFlag;
    }

    return result.ToArray();
}

答案 1 :(得分:1)

假设你的MyEnum有一个Flags属性,为了测试是否设置了一个标志,(标准?)方式是执行二进制&amp;在你的价值和你要测试的旗帜之间: 所以这样的事情应该有效:

internal static MyEnum[] GetFlags(this MyEnum modKey)
{
    List<MyEnum> flags = new List<MyEnum>();
    foreach (var flag in Enum.GetValues(typeof(MyEnum)))
    {
        if (modKey & flag == flag)
            flags.Add((MyEnum)flag);
    }
    return flags.ToArray(); 
}

如果您使用.Net 4或更高版本,则可以使用HasFlag

        if (modKey.HasFlag((MyEnum)flag))
            ...