Bitmask'ed Int to Enum[] or Int[]? c#
Question
I have an enum that looks like this:
enum foo{
a=0,
b=1,
c=2,
d=4
}
Building the flag / bitmask is fine, but is it possible to do something like
int i = 3;
var bar = Enum.Split(foo,i);
Resulting in something like
bar = foo[]{a, b,c};
Thanks.
Solution
Try the following
public static IEnumerable<T> Split<T>(int value) {
foreach (object cur in Enum.GetValues(typeof(T))) {
var number = (int)(object)(T)cur;
if (0 != (number & value)) {
yield return (T)cur;
}
}
}
With this you can now write
int i = 3;
IEnumerable<foo> e = Split<foo>(i);
Note: This only works on enum
values which derive from int
(the default setting). It's also not entirely type safe as T
can't be constrained to only enum
values (nothing to do about that though)
OTHER TIPS
You can use the FlagsAttribute
on the enum and get lots of the functionality for free (no need to work at the bit level).
MSDN describes the attribute as:
Indicates that an enumeration can be treated as a bit field; that is, a set of flags.
The [FlagsAttribute]
allows you to extract all of the valid values.
http://msdn.microsoft.com/en-us/library/system.flagsattribute.aspx
Try this:
TEnum[] EnumSplit<TEnum>(int mask)
{
List<TEnum> values = new List<TEnum>();
foreach(int enumValue in Enum.GetValues(typeof(TEnum)))
{
if(mask & enumValue == enumValue)
values.Add((TEnum)enumValue);
}
return values.ToArray();
}
Call it like this:
var bar = EnumSplit<foo>(i);
Preferably, you want to change it to return IEnumerable<TEnum>
instead of TEnum[]
.
You could do this with a method which pulls the values from the Enum
you pass:
public static T[] EnumSplit<T>(int value) where T : struct
{
// Simplified as Enum.GetValues will complain if T is not an enum
// However, you should add a check to make sure T implements FlagAttribute
return (from vv in Enum.GetValues(typeof(T))
where ((int)vv & value) != 0
select (T)vv).ToArray();;
}
var flags = Enum.GetValues(typeof (/* YourEnumType */))
.Cast</* YourEnumType */>()
.Select(v => enumValue.HasFlag(v))
.ToArray();