Reputation: 9620
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[]?
Upvotes: 6
Views: 11095
Reputation: 195
Using some modern C# features we can do this more elegantly:
static int MaxEnumValue<T>()
where T : struct, Enum
{
return (int)(ValueType)Enum.GetValues<T>().Max();
}
Upvotes: 1
Reputation: 9620
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.
Upvotes: 3
Reputation: 1501646
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();
}
Upvotes: 24
Reputation: 49985
Easy! Using LINQ your loop can be replaced with two lines of code, or just one if you want to munge it all together.
public partial class Form1 : Form
{
private void Form1_Load(object sender, EventArgs e)
{
MyEnum z = MyEnum.Second;
z++;
z++;
//see if a specific value is defined in the enum:
bool isInTheEnum = !Enum.IsDefined(typeof(MyEnum), z);
//get the max value from the enum:
List<int> allValues = new List<int>(Enum.GetValues(typeof(MyEnum)).Cast<int>());
int maxValue = allValues.Max();
}
}
public enum MyEnum
{
Zero = 0,
First = 1,
Second = 2,
Third = 3
}
Upvotes: 0