Как получить сложное представление строки значения перечисления - PullRequest
10 голосов
/ 11 февраля 2011

Допустим, у меня есть следующее перечисление:

[Flags]
public enum SomeType
{    
    Val1 = 0,
    Val2 = 1,
    Val3 = 2,
    Val4 = 4,
    Val5 = 8,
    Val6 = 16,
    All = Val1 | Val2 | Val3 | Val4 | Val5 | Val6
}

и некоторые переменные:

SomeType easyType = SomeType.Val1 | SomeType.Val2;
SomeType complexType = SomeType.All;

Если я хочу просмотреть значения первого перечисления, я могу просто сделать:

foreach(string s in easyType.ToString().Split(','))
{ ... }

Однако, когда я пытаюсь применить тот же подход к 'complexType', я получаю значение 'All', которое, конечно, допустимо, потому что это также одно из возможных значений перечисления.Но есть ли хороший способ на самом деле увидеть, из каких значений создан SomeType.All?Я знаю, что мог бы сделать ручной цикл по всем значениям, подобным этому:

if(complexType.HasFlag(ManualType.Val1) && ...

Ответы [ 4 ]

4 голосов
/ 11 февраля 2011
var result = string.Join(",",
                 Enum.GetValues(typeof(SomeType))
                     .Cast<SomeType>()
                     .Where(v => complexType.HasFlag(v)));

Вы можете написать метод расширения, чтобы избежать повторения.

0 голосов
/ 11 февраля 2011

Если вы используете перечисление для представления данных, которые имеют более глубокий уровень сложности (произвольные группы элементов, «темнота» цвета и т. Д.) И борются из-за этого, я бы предположил, что перечисление является неправильная конструкция программирования для использования.

Использование перечисления для этих задач всегда будет подвержено ошибкам: если я добавлю новый цвет в ваше перечисление, я должен не забыть добавить его также в «Яркий» или «Темный». Это делает ваш код таким же подверженным ошибкам для разработчиков, как и исходная проблема. Однако то, что вы могли бы сделать, это определить class или struct для цвета, у которого есть свойство, указывающее, является ли он ярким или нет. Тогда у вас будет четкая, понятная функциональность, реализованная таким образом, который не дает ложных результатов, как при попытке злоупотребления более простой языковой функцией.

Именно поэтому, например, Color является struct ...

0 голосов
/ 11 февраля 2011

Вот один из возможных способов сделать это, основываясь на ответе Дэнни Чена:

public IEnumerable<T> GetFlags<T>(Predicate<int> hasFlag) 
{
    return GetEnumFlags<T>().Where(f => hasFlag(f)).Cast<T>();
}

private IEnumerable<int> GetEnumFlags<T>()
{
    return Enum.GetValues(typeof(T)).Cast<int>().Where(IsPowerOfTwoOrZero);
}

private bool IsPowerOfTwoOrZero(int v)
{
    return  ((v & (v-1)) == 0);
}

Использование:

void Main()
{
    SomeType easyType = SomeType.Val1 | SomeType.Val2;
    SomeType complexType = SomeType.All;

    GetFlags<SomeType>(v => easyType.HasFlag((SomeType)v));
    GetFlags<SomeType>(v => complexType.HasFlag((SomeType)v));
}

Обратите внимание, что это будет работать для Enums на основе типов, которые можно преобразовать в int.Вы можете создать аналогичные методы для long и т. Д.

0 голосов
/ 11 февраля 2011

Может быть, вам нужно перечислить значения перечисления и проверить каждое из них:

foreach (SomeType item in Enum.GetValues (typeof (SomeType))
{
  if ((complexType & item) == item)
  {
    //...
  }
}
...