Given the enum
:
[Flags]
public enum mytest
{
a = 1,
b = 2,
c = 4
}
I've come up with two ways to represent all values in a single variable:
var OR1 = (mytest)Enum.GetNames(typeof(mytest)).Sum(a => (int)Enum.Parse(typeof(mytest), a));
var OR2 = (mytest)(typeof(mytest).GetEnumValues() as mytest[]).Sum(a => (int)a);
Now, although they both work, is there a neater way? Possibly a .NET method I'm missing?
Edit: For clarification, I need the function to be dynamic - I don't want to calculate it by specifying every single enum
value.
Enum Flags Attribute The idea of Enum Flags is to take an enumeration variable and allow it hold multiple values. It should be used whenever the enum represents a collection of flags, rather than representing a single value. Such enumeration collections are usually manipulated using bitwise operators.
Create enum constructor which accepts multiple values. Assign each constructor argument to a member field in the enum definition. Create getter methods so we can access any of the values assigned to a particular enum constant.
The [Flag] attribute is used when Enum represents a collection of multiple possible values rather than a single value. All the possible combination of values will come. The [Flags] attribute should be used whenever the enumerable represents a collection of possible values, rather than a single value.
There is nothing that requires them to be sequential. Your enum definition is fine and will compile without issue.
If it makes sense to have an All
member, just provide it directly:
[Flags]
public enum mytest
{
a = 1,
b = 2,
c = 4,
All = 7
}
Though, a more idiomatic way to write these could be:
[Flags]
public enum MyTest
{
A = 1,
B = 1 << 0x01,
C = 1 << 0x02,
All = A | B | C
}
This shows the logical progression of the enum values, and in the All
case, makes it easy to add another member.
Use Enumerable.Aggregate()
to bitwise-or them together. This will work even if you have enum values that represent multiple set bits, as opposed to Sum()
.
var myTestValues = (MyTest[]) typeof(MyTest).GetEnumValues();
var sum = myTestValues.Aggregate((a, b) => a | b);
sum.Dump();
It's a little tricky to make this generic because you can't constrain generic types to be enums, nor do the primitive types have any subtype relationship to one another. The best I could come up with assumes that the underlying type is int
which should be good enough most of the time:
TEnum AllEnums<TEnum>()
{
var values = typeof(TEnum).GetEnumValues().Cast<int>();
return (TEnum) (object) values.Aggregate((a,b) => a|b);
}
For a generic method, use Linq's Enumerable.Aggregate extension method;
var flags = Enum.GetValues(typeof(mytest))
.Cast<int>()
.Aggregate(0, (s, f) => s | f);
Or in a wrapper method
TEnum GetAll<TEnum>() where TEnum : struct
{
return (TEnum) (object)
Enum.GetValues(typeof(TEnum))
.Cast<int>()
.Aggregate(0, (s, f) => s | f);
}
full credit for this double-cast trick goes to @millimoose
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With