English 中文(简体)
Finding the Highest Value in an Enumeration
原标题:

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

最佳回答

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.

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
}

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();
}




相关问题
Anyone feel like passing it forward?

I m the only developer in my company, and am getting along well as an autodidact, but I know I m missing out on the education one gets from working with and having code reviewed by more senior devs. ...

NSArray s, Primitive types and Boxing Oh My!

I m pretty new to the Objective-C world and I have a long history with .net/C# so naturally I m inclined to use my C# wits. Now here s the question: I feel really inclined to create some type of ...

C# Marshal / Pinvoke CBitmap?

I cannot figure out how to marshal a C++ CBitmap to a C# Bitmap or Image class. My import looks like this: [DllImport(@"test.dll", CharSet = CharSet.Unicode)] public static extern IntPtr ...

How to Use Ghostscript DLL to convert PDF to PDF/A

How to user GhostScript DLL to convert PDF to PDF/A. I know I kind of have to call the exported function of gsdll32.dll whose name is gsapi_init_with_args, but how do i pass the right arguments? BTW, ...

Linqy no matchy

Maybe it s something I m doing wrong. I m just learning Linq because I m bored. And so far so good. I made a little program and it basically just outputs all matches (foreach) into a label control. ...

热门标签