С#:Получение ключа с наименьшим значением в побитовом Enum

StackOverflow https://stackoverflow.com/questions/2344431

  •  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.

  1. Получите список всех значений в перечислении
  2. Сопоставим эти значения с каким-то сопоставимый тип данных
  3. Сравните все значения и сохраните трек самого низкого
  4. Преобразовать наименьшее значение обратно в тип перечисления

Это должна быть итеративная реализация, в которой вы тестируете биты.Я бы сделал что-то вроде этого.

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 не имеют префикса имени типа, поэтому они не будут ссылаться на имена перечислений, для которых они, по-видимому, предназначены.

Кроме того, если вы используете побитовое И для объединения флагов, результат будет содержать все включенные флаги. все параметры - в данном случае нет.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top