С#:Получение ключа с наименьшим значением в побитовом Enum
-
23-09-2019 - |
Вопрос
У меня есть такое перечисление
[Flags]
public enum Key
{
None = 0,
A = 1,
B = 2,
C = 4
}
У меня есть следующее
Key k1 = Key.A | Key.B | Key.C;
Я хочу получить ключ в k1, имеющий наименьшее значение.Как мне это сделать?
Пример:
Key k1 = Key.A | Key.B | Key.C; // I want a
Key k2 = Key.B | Key.C; // I want b
Key k3 = Key.A | Key.C; // I want a
Решение
Keys key = Keys.b | Keys.c;
var lowest = Enum.GetValues(typeof(Keys))
.Cast<Keys>()
.OrderBy(x => x)
.FirstOrDefault(x => key.HasFlag(x));
Немного более эффективная версия метода LINQ в стиле .NET 4.0.
Другие советы
Вы можете использовать небольшой трюк:
Key key = Key.B | Key.C;
Key lowest = (Key)((int)key & -(int)key);
Keys key = Keys.b | Keys.c;
var lowest = Enum.GetValues(typeof(Keys))
.OfType<Keys>()
.Where(x => (x & key) != 0)
.OrderBy(x => x)
.DefaultIfEmpty((Keys)0);
Console.WriteLine(lowest);
Если у вас есть только 3 значения в перечислении, вероятно, самый быстрый и простой способ — проверить их одно за другим.Однако в качестве общего решения вы можете попытаться преобразовать значение k1
в целое число, найдите наибольшую степень 2, которая делит его, и преобразуйте ее обратно в значение перечисления Keys.
- Получите список всех значений в перечислении
- Сопоставим эти значения с каким-то сопоставимый тип данных
- Сравните все значения и сохраните трек самого низкого
- Преобразовать наименьшее значение обратно в тип перечисления
Это должна быть итеративная реализация, в которой вы тестируете биты.Я бы сделал что-то вроде этого.
unsigned int k = (unsigned int) k1;
int pos = -1;
while (k) {
pos++;
if (k & 0x1) break;
k >>= 1;
}
Keys lowestKey = 0;
if (pos >= 0) lowestKey = 0x1 << pos;
Код, который вы изначально опубликовали, не имеет смысла:a+b+c не имеют префикса имени типа, поэтому они не будут ссылаться на имена перечислений, для которых они, по-видимому, предназначены.
Кроме того, если вы используете побитовое И для объединения флагов, результат будет содержать все включенные флаги. все параметры - в данном случае нет.