I'm using a enum with flags attribute as a way of tracking status.
An example is the following:
Created = 1
Completed = 2
Dispatched = 4
Without writing anything too rigid (if check this, do that, if check that, do this) i want to be able to find the highest flag which has been set so in this example:
Item.Status = Status.Created | Status.Completed
the mythical method would return 2 - as completed is the flag set with the highest value.
GetMaxSetFlagValue(Item.Status) // returns 2
I've found questions which revolved around the actual enum, just not a value which uses flags. I'm fairly sure this could be achieved with Linq...?
Something like the following should work:
static int GetMaxSetFlagValue<T>(T flags) where T : struct
{
int value = (int)Convert.ChangeType(flags, typeof(int));
IEnumerable<int> setValues = Enum.GetValues(flags.GetType()).Cast<int>().Where(f => (f & value) == f);
return setValues.Any() ? setValues.Max() : 0;
}
The method will fail if T is not an enum type, so a check should preferably be performed in the beginning of the method. Also it will not work for an enum with an underlying type larger than int
(i.e. long
).
This is the extension method I use. It will give you the enum back
var maxStatus = Item.Status.GetFlags().Max();
Output: maxStatus = Completed
public static class EnumExtensions {
/// <summary>Enumerates get flags in this collection.</summary>
///
/// <param name="value">The value.
/// </param>
///
/// <returns>An enumerator that allows foreach to be used to process get flags in this collection.</returns>
public static IEnumerable<T> GetFlags<T> (this T value) where T : struct {
return GetFlags (value, Enum.GetValues (value.GetType ()).Cast<T> ().ToArray ());
}
/// <summary>Enumerates get flags in this collection.</summary>
///
/// <param name="value"> The value.
/// </param>
/// <param name="values">The values.
/// </param>
///
/// <returns>An enumerator that allows foreach to be used to process get flags in this collection.</returns>
private static IEnumerable<T> GetFlags<T> (T value, T [] values) where T : struct {
if (!typeof (T).IsEnum) {
throw new ArgumentException ("Type must be an enum.");
}
ulong bits = Convert.ToUInt64 (value);
var results = new List<T> ();
for (int i = values.Length - 1; i >= 0; i--) {
ulong mask = Convert.ToUInt64 (values [i]);
if (i == 0 && mask == 0L)
break;
if ((bits & mask) == mask) {
results.Add (values [i]);
bits -= mask;
}
}
if (bits != 0L)
return Enumerable.Empty<T> ();
if (Convert.ToUInt64 (value) != 0L)
return results.Reverse<T> ();
if (bits == Convert.ToUInt64 (value) && values.Length > 0 && Convert.ToUInt64 (values [0]) == 0L)
return values.Take (1);
return Enumerable.Empty<T> ();
}
}
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