Как получить строковое представление значения enum

Скажем, у меня есть это перечисление:

[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", я получаю значение "Все", что, конечно, верно, потому что это также одно из возможных значений перечисления. Но есть ли опрятный способ увидеть, какие значения есть SomeType. Все создано? Я знаю, что могу сделать ручную петлю через все такие значения:

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

Ответ 1

var result = string.Join(",",
                 Enum.GetValues(typeof(SomeType))
                     .Cast<SomeType>()
                     .Where(v => complexType.HasFlag(v)));

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

Ответ 2

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

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

Ответ 3

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

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 и т.д.

Ответ 4

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

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

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