Я придумал эту часть кода, который преобразовывает флаги набора в переменной Перечисления Флага типа и возвращает флаги набора как целые числа. Я хотел бы знать, является ли это лучшим подходом.
Перечисление в качестве примера:
[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
Как Вы видите, чтобы сделать это я делаю следующее:
Это работает, но я просто не думаю, что это - лучший подход. Какие-либо предложения для улучшения этого бита кода?
Чтобы он оставался похожим на 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
.
Что ж, вы можете заменить шаги 1-3 вызовом Enum.GetValues
. А затем используйте побитовый оператор &
, чтобы проверить, какие из них установлены в вашем значении. Это будет намного быстрее, чем работать со строками.
Этот метод поддерживает флаги шириной более одного бита. Если все биты независимы, просто сделайте то, что сказал Анон .
Просто приведите к типу 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;