C # Преобразование установленных флагов в переменной перечисления флагов типов в массив целых чисел - PullRequest
10 голосов
/ 09 июля 2010

Я придумал этот фрагмент кода, который преобразовывает установленные флаги в переменную типа Flag Enumeration и возвращает установленные флаги как целые числа. Я хотел бы знать, если это лучший подход.

Пример перечисления:

<code>[Flags]
enum Status {
  None = 0x0,
  Active = 0x1,
  Inactive = 0x2,
  Canceled = 0x4,
  Suspended = 0x8
}

Метод расширения, который преобразует установленные флаги в массив int, который я придумал:

public static class Extensions
{
    public static int[] ToIntArray(this System.Enum o) 
    {
        return o.ToString()
            .Split(new string[] { ", " }, StringSplitOptions.None)
            .Select(i => (int)Enum.Parse(o.GetType(), i))
            .ToArray();
    }
}

Вот как я это использую:

Status filterStatus = Status.Suspended | Status.Canceled;

int[] filterFlags = filterStatus.toIntArray();

foreach (int flag in filterFlags) {
   Console.WriteLine("{0}\n", flag);
}

Будет выведено:

4
8

Как видите, для этого я делаю следующее:

  1. Преобразование переменной в строку. Выводит что-то вроде: Приостановлено, Отменено
  2. Разделение этой строки на массив строк: {"Suspended", "Cancelled"}
  3. Преобразование этой строки в значение перечисления с помощью Enum.Parse.
  4. Преобразование значения в целое число.
  5. Преобразование IEnumerable в int [].

Это работает, но я просто не думаю, что это лучший подход. Любые предложения по улучшению этого кода?

Ответы [ 3 ]

11 голосов
/ 09 июля 2010

Чтобы сохранить его в стиле linq

var flags = Enum.GetValues(typeof(Status))
                .Cast<int>()
                .Where(f=> f & o == f)
                .ToList();

Один из недостатков этого подхода состоит в том, что он будет включать в себя совокупные значения перечисления.Например:

[Flags]
public enum Status
{
    None = 0,
    One = 1,
    Two = 2,
    All = One | Two,
}

var flags = Enum.GetValues(typeof(Status))
                .Cast<int>()
                .Where(f=> f & o == f)
                .ToList();

Здесь flags будет иметь 1, 2, 3, а не просто 1, 2.

3 голосов
/ 09 июля 2010

Просто приведите к int, а затем распечатайте отдельные биты.

int x = (int)o
List<int> flags = new List<int>();
for(int i = 1; i < (1 << 30); i <<= 1)
    if(x & i != 0)
        flags.Add(i);
return flags;
0 голосов
/ 09 июля 2010

Ну, вы можете заменить шаги 1-3 вызовом Enum.GetValues.А затем используйте побитовый оператор &, чтобы проверить, какие из них установлены в вашем значении.Это будет намного быстрее, чем работа со строками.

Этот метод будет поддерживать флаги шириной более одного бита.Если все биты независимы, просто сделайте то, что сказал Анон .

...