Извлечение перечислимых флагов в список с помощью универсального метода?

идеология

Я пытаюсь извлечь флаги перечисления из значения и преобразовать их в List или же HashSet с 0 (нет) исключается.

Структура, на которую я нацеливаюсь, .Net Core 2.1, Я смог сделать это с определенными перечислениями, однако я хочу расширить этот метод, чтобы принимать любые виды перечислений, основанные на int, используя универсальный метод для преобразования в List или же HashSet уменьшить шаблон кода.

Код

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) { }

Но я полностью потерян, куда идти отсюда, поэтому любая помощь очень ценится.

1 ответ

Решение

Может быть, это

Дано

[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

Отказ от ответственности: очевидно, должной осмотрительности и отказоустойчивости требуется

Полная демонстрация здесь

Другие вопросы по тегам