如何列出基于组合的枚举

时间:2014-10-29 23:57:44

标签: c#

可以列出组合的标志。

使用ProfileTypeFlag.SupplierMaster获取“供应商|主|外部”的列表

我正在尝试使用此代码。但他们返回所有的枚举;

    public List<string> SetRoles(ProfileTypeFlag role)
        {
            List<string> result = new List<string>();
            foreach (ProfileTypeFlag r in Enum.GetValues(typeof(ProfileTypeFlag)))
            {
                if ((role & r) != 0) result.Add(r.ToString());
            }

          return result;
        }


[Flags]
 public enum ProfileTypeFlag : uint
    {
        None = 0,
        Customer = 1,
        Supplier = 2,
        Internal = 4,
        Delegate = 8,
        Master = 16,
        External = 32,
        CustomerMaster = Customer | Master | External,
        SupplierMaster = Supplier | Master | External
}

3 个答案:

答案 0 :(得分:1)

稍微调整一下if声明:

if ((role & r) == r && r != ProfileTypeFlag.None && role != r)

或者您可以使用HasFlag(相当于role & r == r):

if (role.HasFlag(r) && r != ProfileTypeFlag.None && role != r)

基本上,如果角色包含标志,那么它不是None标志,而不是角色本身,然后将其添加到列表中。

考虑到这一点,您可以将整个功能更改为:

public List<string> SetRoles(ProfileTypeFlag role)
{    
    return
        Enum.GetValues(typeof(ProfileTypeFlag))
            .Cast<ProfileTypeFlag>()
            .Where(r => r != ProfileTypeFlag.None)
            .Where(r => r != role)
            .Where(r => role.HasFlag(r))
            .Select(r => r.ToString())
            .ToList();
}

正如@Lucas所指出的,如果您的枚举值包含复合标记,则上述解决方案无法正常工作。

对此的一个解决方案是在遇到它们时删除标记值:

public List<string> SetRoles(ProfileTypeFlag role)
{    
    var result = new List<string>();

    foreach (ProfileTypeFlag r in Enum.GetValues(typeof(ProfileTypeFlag)))
    {
        if (role.HasFlag(r) && r != ProfileTypeFlag.None) 
        {
            result.Add(r.ToString());
            role &= ~r;
        }
    }

    return result;
}

答案 1 :(得分:1)

以下是您的解决方案:

public static string GetFlagsStringFromUInt32Enum<TEnum>(TEnum value)
    where TEnum : struct
{
    var sb = new StringBuilder();

    for(var i = 0; i < 32; ++i)
    {
        var bit = (uint)1 << i;
        if (((uint)(object)value & bit) != 0)
            sb.Append((TEnum)(object)bit).Append(" | ");
    }

    if (sb.Length > 0)
        sb.Length -= 3;

    return sb.ToString();
}

Demo

这将基于像您这样的uint的枚举,我很难实现一般解决方案。

答案 2 :(得分:0)

要提供稍微不同的方法,您可以使用此函数来获取“set”枚举:

static IEnumerable<Enum> GetFlags(Enum input)
{
    foreach (Enum value in Enum.GetValues(input.GetType()))
        if (input.HasFlag(value))
            yield return value;
}

归功于@Greg(Iterate over values in Flags Enum?

然后这样称呼它:

List<string> names = GetFlags(enumValue).Select(e => e.ToString()).ToList();