How to get complex enum value string representation
Let's say I have this enum:
[Flags]
public enum SomeType
{
Val1 = 0,
Val2 = 1,
Val3 = 2,
Val4 = 4,
Val5 = 8,
Val6 = 16,
All = Val1 | Val2 | Val3 | Val4 | Val5 | Val6
}
and some variables:
SomeTyp开发者_如何学JAVAe easyType = SomeType.Val1 | SomeType.Val2;
SomeType complexType = SomeType.All;
If I want to loop through values of the first enum I can simply do:
foreach(string s in easyType.ToString().Split(','))
{ ... }
However, when I try to apply the same approach to the 'complexType' I get value 'All', which is of course valid because it's also one of possible values of the enum. But, is there a neat way to actually see of what values is the SomeType.All created of? I know I could make a manual loop through all the values like that:
if(complexType.HasFlag(ManualType.Val1) && ...
var result = string.Join(",",
Enum.GetValues(typeof(SomeType))
.Cast<SomeType>()
.Where(v => complexType.HasFlag(v)));
You can write an extension method to avoid repeating yourself.
Maybe you need to enumerate the enum values and test each one:
foreach (SomeType item in Enum.GetValues (typeof (SomeType))
{
if ((complexType & item) == item)
{
//...
}
}
Here's one possible way to do it, building on Danny Chen's answer:
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);
}
Usage:
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));
}
Note this will work for Enums based on types castable to int
. You can create similar methods for long
etc.
If you're using an enum to represent data that has some deeper level of complexity (arbitrary groups of elements, "darkness" of colour, etc.) and struggling because of that, I'd suggest that an enum is the wrong programming construct to be using.
Using an enum for these tasks will always be error prone: if I add a new colour to your enum, I have to remember to add it to "Bright" or "Dark" too. That makes your code just as error prone for developers as the original problem. What you could do, however, is define a class
or struct
for colour that has a property indicating whether it's bright or not. Then you'll have clear, understandable functionality - implemented in a way that doesn't give spurious results as when you're trying to misuse a simpler language feature.
That, for example, is why Color
is a struct
...
精彩评论