C#, Преобразовывающий набор, отмечает в переменной перечисления флага типа к массиву целых чисел

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

Перечисление в качестве примера:

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

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

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. Разделение той строки в массив строк: {"Приостановленный", "Отмененный"}
  3. Преобразование той строки к перечислимой величине с Перечислением. Синтаксический анализ.
  4. Кастинг значения к целому числу.
  5. Преобразование IEnumerable к интервалу [].

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

10
задан Cameri 8 July 2010 в 21:53
поделиться

3 ответа

Чтобы он оставался похожим на 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();

Здесь флаги будут иметь 1, 2, 3 , а не только 1, 2 .

12
ответ дан 3 December 2019 в 22:34
поделиться

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

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

0
ответ дан 3 December 2019 в 22:34
поделиться

Просто приведите к типу 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;
3
ответ дан 3 December 2019 в 22:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: