Перебирать значения в Flags Enum? - PullRequest
119 голосов
/ 13 ноября 2010

Если у меня есть переменная, содержащая перечисление flags, могу ли я как-то перебрать значения битов в этой конкретной переменной? Или я должен использовать Enum.GetValues ​​для перебора всего перечисления и проверки, какие из них установлены?

Ответы [ 14 ]

1 голос
/ 13 ноября 2010

Вы можете использовать итератор из Enum. Начиная с кода MSDN:

public class DaysOfTheWeek : System.Collections.IEnumerable
{
    int[] dayflag = { 1, 2, 4, 8, 16, 32, 64 };
    string[] days = { "Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun" };
    public string value { get; set; }

    public System.Collections.IEnumerator GetEnumerator()
    {
        for (int i = 0; i < days.Length; i++)
        {
            if value >> i & 1 == dayflag[i] {
                yield return days[i];
            }
        }
    }
}

Это не проверено, поэтому, если я допустил ошибку, не стесняйтесь звать меня. (очевидно, это не повторный вход.) Вам нужно заранее присвоить значение или разбить его на другую функцию, которая использует enum.dayflag и enum.days. Вы могли бы пойти куда-нибудь с контуром.

0 голосов
/ 09 июля 2019

Все ответы хорошо работают с простыми флагами, вы, вероятно, столкнетесь с проблемами при объединении флагов.

[Flags]
enum Food
{
  None=0
  Bread=1,
  Pasta=2,
  Apples=4,
  Banana=8,
  WithGluten=Bread|Pasta,
  Fruits = Apples | Banana,
}

, вероятно, необходимо добавить проверку, чтобы проверить, является ли само значение enum комбинацией.Вам, вероятно, понадобится что-то подобное, опубликованное здесь Хенком ван Бойеном , чтобы удовлетворить ваши требования (вам нужно немного прокрутить вниз)

0 голосов
/ 15 марта 2018

Это может быть так же, как следующий код:

public static string GetEnumString(MyEnum inEnumValue)
{
    StringBuilder sb = new StringBuilder();

    foreach (MyEnum e in Enum.GetValues(typeof(MyEnum )))
    {
        if ((e & inEnumValue) != 0)
        {
           sb.Append(e.ToString());
           sb.Append(", ");
        }
    }

   return sb.ToString().Trim().TrimEnd(',');
}

Он входит внутрь, если только когда значение enum содержится в значении

0 голосов
/ 03 июня 2016

Вы можете сделать это напрямую, конвертировав в int, но вы потеряете проверку типов.Я думаю, что лучше всего использовать что-то похожее на мое предложение.Все время держите правильный тип.Преобразование не требуется.Это не идеально из-за бокса, который добавит небольшой удар по производительности.

Не идеально (бокс), но он делает работу без предупреждения ...

/// <summary>
/// Return an enumerators of input flag(s)
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static IEnumerable<T> GetFlags<T>(this T input)
{
    foreach (Enum value in Enum.GetValues(input.GetType()))
    {
        if ((int) (object) value != 0) // Just in case somebody has defined an enum with 0.
        {
            if (((Enum) (object) input).HasFlag(value))
                yield return (T) (object) value;
        }
    }
}

Использование:

    FileAttributes att = FileAttributes.Normal | FileAttributes.Compressed;
    foreach (FileAttributes fa in att.GetFlags())
    {
        ...
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...