I have an enum with a Flags attribute.
My question is, I'd like to get an integer bitmask of all of the options without manual开发者_如何学运维ly combining all the bits myself. I want to do this to compare to some other int field, and I want to protect in case a future developer ads more bit options to the enum.
Another thing is the bits in my enum flags will be all manually assigned, so I cannot simply get the next value and subtract 1.
If I understood what you asked correctly this should work for you:
Enum.GetValues(typeof(Enum)).Cast<int>().Sum();
You can then cast it back to your typeof(Enum)
:
[Flags]
public enum Values
{
Value_1 = 1,
Value_2 = 2,
Value_3 = 4,
Value_4 = 8,
Value_5 = 16,
Value_6 = 32,
Value_7 = 64,
Value_8 = 128,
Value_9 = 256
}
static void Main(string[] args)
{
Values values = (Values)Enum.GetValues(typeof(Values)).Cast<int>().Sum();
}
// uses a ulong to handle all possible underlying types without error
var allFlags = Enum.GetValues(typeof(YourEnumType))
.Cast<YourEnumType>()
.Aggregate((YourEnumType)0, (a, x) => a | x, a => (ulong)a);
Have a look at my Unconstrained Melody project, which does evil things to allow nice features to be built on generic methods constrained to enums and delegates.
In this case, I think you'd want to call Flags.GetUsedBits<YourEnumType>()
.
If you don't mind using an extra (very small) library, I'd like to think that Unconstrained Melody makes life nicer when dealing with flags. If you have any feature requests, I'd be happy to have a look :)
Kind of crude but something like this?
[Flags]
enum SomeFlags
{
Flag1 = 1,
Flag2 = 2,
Flag3 = 4,
Flag4 = 16,
Flag5 = 32,
Flag6 = 64
}
static void Main(string[] args)
{
SomeFlags flags = 0;
SomeFlags[] values = (SomeFlags[])Enum.GetValues(typeof(SomeFlags));
Array.ForEach<SomeFlags>(values, delegate(SomeFlags v) { flags |= v; });
int bitMask = Convert.ToInt32(flags);
}
Here's a way to do it, using ideas from the generic operators written by Jon Skeet and Marc Gravell :
void Main()
{
Console.WriteLine(CombineAllFlags<MyEnum>()); // Prints "Foo, Bar, Baz"
}
[Flags]
public enum MyEnum
{
Foo = 1,
Bar = 2,
Baz = 4
}
public static TEnum CombineAllFlags<TEnum>()
{
TEnum[] values = (TEnum[])Enum.GetValues(typeof(TEnum));
TEnum tmp = default(TEnum);
foreach (TEnum v in values)
{
tmp = EnumHelper<TEnum>.Or(tmp, v);
}
return tmp;
}
static class EnumHelper<T>
{
private static Func<T, T, T> _orOperator = MakeOrOperator();
private static Func<T, T, T> MakeOrOperator()
{
Type underlyingType = Enum.GetUnderlyingType(typeof(T));
ParameterExpression xParam = Expression.Parameter(typeof(T), "x");
ParameterExpression yParam = Expression.Parameter(typeof(T), "y");
var expr =
Expression.Lambda<Func<T, T, T>>(
Expression.Convert(
Expression.Or(
Expression.Convert(xParam, underlyingType),
Expression.Convert(yParam, underlyingType)),
typeof(T)),
xParam,
yParam);
return expr.Compile();
}
public static T Or(T x, T y)
{
return _orOperator(x, y);
}
}
This code dynamically creates a delegate that combines enum values with the OR operator
精彩评论