Нахождение наибольшего значения в перечислении - PullRequest
6 голосов
/ 17 ноября 2009

Я пишу метод, который определяет самое высокое значение в перечислении .NET, чтобы я мог создать BitArray с одним битом для каждого значения перечисления:

pressedKeys = new BitArray(highestValueInEnum<Keys>());

Мне нужно это для двух разных перечислений, поэтому я превратил его в универсальный метод:

/// <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;
}

Как видите, я приведу возвращаемое значение Enum.GetValues ​​() к int [], а не к EnumType []. Это потому, что я не могу привести EnumType (который является параметром универсального типа) к int позже.

Код работает. Но так ли это? Могу ли я всегда приводить возврат из Enum.GetValues ​​() к int []?

Ответы [ 3 ]

20 голосов
/ 17 ноября 2009

Нет, вы не можете безопасно привести к int[]. Типы enum не всегда используют int в качестве базового значения. Если вы ограничиваете себя перечислимыми типами, которые do имеют базовый тип int, то все будет в порядке.

Это похоже на то, что вы (или я) могли бы расширить Неограниченная мелодия для поддержки, если хотите, способом, который действительно ограничивал тип во время компиляции типом enum и работал для любой тип перечисления, даже те, у которых есть базовые основания, такие как long и ulong.

Без неограниченной мелодии вы все равно можете сделать это в общем виде, используя тот факт, что все типы перечислений эффективно реализуют IComparable надлежащим образом. Если вы используете .NET 3.5, это однострочный:

private static TEnum GetHighestValue<TEnum>() {
  return Enum.GetValues(typeof(TEnum)).Cast<TEnum>().Max();
}
3 голосов
/ 17 ноября 2009

Согласно совету Джона Скита (и спасибо вам, slugster), это обновленный код, теперь использующий IComparable, потому что я все еще ориентируюсь на .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;
}

Для тех, кто захватывает код, вы можете добавить дополнительную проверку, чтобы он не взрывался при пустых перечислениях.

0 голосов
/ 17 ноября 2009

Легко! Используя LINQ, ваш цикл может быть заменен двумя строками кода или только одной, если вы хотите объединить все вместе.

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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...