Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding the Highest Value in an Enumeration

Tags:

arrays

c#

enums

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[]?

like image 775
Cygon Avatar asked Nov 17 '09 07:11

Cygon


People also ask

How do you find the max value of an enum?

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.

What is an enumeration 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.

What is the size of enumeration?

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.


2 Answers

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();
}
like image 178
Jon Skeet Avatar answered Oct 04 '22 08:10

Jon Skeet


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.

like image 43
Cygon Avatar answered Oct 04 '22 07:10

Cygon