如何在组合中列出基于枚举

本文关键字:于枚举 枚举 组合 | 更新日期: 2023-09-27 18:28:32

是否可以组合列出一个标志。

使用ProfileTypeFlag.SupplierMaster只获取"Supplier|Master|External"的列表

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

    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
}

如何在组合中列出基于枚举

这里有一个适合您的解决方案:

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();
}

演示

这将适用于基于uint的枚举,就像您的一样,我不想实现通用解决方案。

只需稍微调整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;
}

为了提供一种稍微不同的方法,您可以使用此函数来获取"set"enums:

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

归功于@Greg(遍历Flags Enum中的值?)

然后这样称呼它:

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