Как получить строковое представление значения 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
...