提取枚举标志以使用通用方法列出?

Extracting enum flags to list with generic method?

意识形态

我正在尝试从值中提取枚举标志并将它们转换为 ListHashSet 并排除 0 (None)。

我的目标框架是 .Net Core 2.1。我已经能够使用特定的枚举来执行此操作,但是,我想扩展此方法以接受任何类型的基于 int 的枚举,使用通用方法转换为 ListHashSet 减少样板代码。

代码

public enum Numbers
{
    None = 0,
    One  = 1,
    Two  = 2,
    Four = 4
}

public enum Teams
{
    None       = 0,
    Stars      = 1,
    Blackhawks = 2,
    Penguins   = 4,
    Devils     = 8
}

public static List<Numbers> EnumToList(Numbers n)
{
    List<Numbers> numberList = new List<Numbers>();

    // Extract values until we hit None / 0.
    while (n != 0)     // Originally: (n != Numbers.None)
    {
        foreach (Numbers i in Enum.GetValues(typeof(Numbers)))
        {
            if (n == 0)
                break;  // Prevent excess looping.

            if ((n & i) == i && i != Numbers.None)
            {   // Found a valid item.
                numberList.Add(i);  
                n &= ~i;    // Remove the value.
            }
        }
    }

    return numberList;
}

static void Main(string[] args)
{
    Numbers nums = Numbers.One | Numbers.Four;

    List<Numbers> items = EnumToList(nums);
    if (items.Count > 0)
    {
        foreach (Numbers n in items)
        {
            Console.WriteLine($"Extracted Value: {Enum.GetName(typeof(Numbers), n)}");
        }
    }

    Console.WriteLine("Press enter to exit.");
    Console.ReadLine();
}

结果

Extracted Value: One
Extracted Value: Four
Press enter to exit.

期望的能力和结果

通过相同的函数传递 Teams 类型的标志以获取列表。

Teams t = Teams.Stars | Teams.Blackhawks | Teams.Devils;
List<Teams> teams = EnumToList(t);

结果:

Extracted Value: Stars
Extracted Value: Blackhawks
Extracted Value: Devils
Press enter to exit.

结论

我知道我将不得不使用通用方法,例如:

public static List<TEnum> EnumToList<TEnum>(TEnum value) { }

但我完全不知道从这里去哪里,所以非常感谢任何帮助。

也许这个

给定

[Flags]
public enum TestEnum
{
    None = 0,
    AA = 1,
    BB = 2,
    CC = 4,
    DD = 8,
}

方法

public static IEnumerable<T> EnumerateMask<T>(Enum mask)
    => Enum.GetValues(typeof (T))
           .Cast<Enum>()
           .Where(mask.HasFlag)
           .Cast<T>()
           .Skip(1);

用法

var mask = TestEnum.AA | TestEnum.None | TestEnum.DD;

foreach (var value in EnumerateMask<TestEnum>(mask))
    Console.WriteLine(value);

输出

AA
DD

免责声明:显然需要尽职调查和容错

Full Demo Here