I'm writing a method which determines the highest value in a .NET enumeration so I can create a BitArray with one bit for each enum value:
pressedKeys = new BitArray(highestValueInEnum<Keys>());
I need this on two different enumerations, so I turned it into a generic method:
/// <summary>Returns the highest value encountered in an enumeration</summary>
/// <typeparam name="EnumType">
/// Enumeration of which the highest value will be returned
/// </typeparam>
/// <returns>The highest value in the enumeration</returns>
private static int highestValueInEnum<EnumType>() {
int[] values = (int[])Enum.GetValues(typeof(EnumType));
int highestValue = values[0];
for(int index = 0; index < values.Length; ++index) {
if(values[index] > highestValue) {
highestValue = values[index];
}
}
return highestValue;
}
As you can see, I'm casting the return value of Enum.GetValues() to int[], not to EnumType[]. This is because I can't cast EnumType (which is a generic type parameter) to int later.
The code works. But is it valid? Can I always cast the return from Enum.GetValues() to int[]?
This is slightly nitpicky but the actual maximum value of any enum is Int32. MaxValue (assuming it's a enum derived from int ). It's perfectly legal to cast any Int32 value to an any enum regardless of whether or not it actually declared a member with that value.
An enumeration is a data type that consists of a set of named values that represent integral constants, known as enumeration constants. An enumeration is also referred to as an enumerated type because you must list (enumerate) each of the values in creating a name for each of them.
On an 8-bit processor, enums can be 16-bits wide. On a 32-bit processor they can be 32-bits wide or more or less. The GCC C compiler will allocate enough memory for an enum to hold any of the values that you have declared. So, if your code only uses values below 256, your enum should be 8 bits wide.
No, you can't safely cast to int[]
. Enum types don't always use int
as an underlying value. If you restrict yourself to enum types which do have an underlying type of int
, it should be fine though.
This feels like something you (or I) could extend Unconstrained Melody to support if you wanted - in a way which genuinely constrained the type to be an enum type at compile time, and worked for any enum type, even those with underlying bases such as long
and ulong
.
Without Unconstrained Melody, you can still do this in a general way using the fact that all the enum types effectively implement IComparable
appropriately. If you're using .NET 3.5 it's a one-liner:
private static TEnum GetHighestValue<TEnum>() {
return Enum.GetValues(typeof(TEnum)).Cast<TEnum>().Max();
}
As per Jon Skeet's advice (and thank you too, slugster), this is the updated code, now using IComparable because I'm still targeting .NET 2.0.
/// <summary>Returns the highest value encountered in an enumeration</summary>
/// <typeparam name="EnumType">
/// Enumeration of which the highest value will be returned
/// </typeparam>
/// <returns>The highest value in the enumeration</returns>
private static EnumType highestValueInEnum<EnumType>() where EnumType : IComparable {
EnumType[] values = (EnumType[])Enum.GetValues(typeof(EnumType));
EnumType highestValue = values[0];
for(int index = 0; index < values.Length; ++index) {
if(values[index].CompareTo(highestValue) > 0) {
highestValue = values[index];
}
}
return highestValue;
}
For anyone grabbing the code, you might want to add an additional check so it doesn't blow up on empty enums.
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