Получение максимального значения перечисления

StackOverflow https://stackoverflow.com/questions/203377

  •  03-07-2019
  •  | 
  •  

Вопрос

Как вы получаете максимальное значение перечисления?

Это было полезно?

Решение

Enum.getValues(), похоже, возвращает значения по порядку, так что вы можете сделать что-то вроде этого:

// given this enum:
public enum Foo
{
    Fizz = 3, 
    Bar = 1,
    Bang = 2
}

// this gets Fizz
var lastFoo = Enum.GetValues(typeof(Foo)).Cast<Foo>().Last();

Редактировать

Для тех, кто не желает читать комментарии:Вы также можете сделать это таким образом:

var lastFoo = Enum.GetValues(typeof(Foo)).Cast<Foo>().Max();

...который будет работать, когда некоторые из ваших значений enum будут отрицательными.

Другие советы

Я согласен с ответом Мэтта.Если вам нужны только значения min и max int, то вы можете сделать это следующим образом.

Максимальный:

Enum.GetValues(typeof(Foo)).Cast<int>().Max();

Минимальный:

Enum.GetValues(typeof(Foo)).Cast<int>().Min();

Согласно ответу Мэтта Гамильтона, я подумал о создании для него метода расширения.

С тех пор как ValueType не принимается в качестве ограничения параметра универсального типа, я не нашел лучшего способа ограничить T Для Enum но вот что.

Любые идеи были бы действительно оценены.

PS.пожалуйста, не обращайте внимания на мою неявность VB, мне нравится использовать VB таким образом, в этом сила VB, и именно поэтому я люблю VB.

Как бы то ни было, вот оно:

C#:

static void Main(string[] args)
{
    MyEnum x = GetMaxValue<MyEnum>();
}

public static TEnum GetMaxValue<TEnum>() 
    where TEnum : IComparable, IConvertible, IFormattable
    //In C#>=7.3 substitute with 'where TEnum : Enum', and remove the following check:
{
    Type type = typeof(TEnum);

    if (!type.IsSubclassOf(typeof(Enum)))
        throw new
            InvalidCastException
                ("Cannot cast '" + type.FullName + "' to System.Enum.");

    return (TEnum)Enum.ToObject(type, Enum.GetValues(type).Cast<int>().Last());
}

enum MyEnum
{
    ValueOne,
    ValueTwo
}

VB:

Public Function GetMaxValue _
    (Of TEnum As {IComparable, IConvertible, IFormattable})() As TEnum

    Dim type = GetType(TEnum)

    If Not type.IsSubclassOf(GetType([Enum])) Then _
        Throw New InvalidCastException _
            ("Cannot cast '" & type.FullName & "' to System.Enum.")

    Return [Enum].ToObject(type, [Enum].GetValues(type) _
                        .Cast(Of Integer).Last)
End Function

Это немного придирчиво, но фактическим максимальным значением любого перечисления является Int32.MaxValue (при условии, что это перечисление, производное от int).Совершенно законно приводить любое значение Int32 к any enum независимо от того, действительно ли в нем объявлен элемент с этим значением.

Юридическая информация:

enum SomeEnum
{
    Fizz = 42
}

public static void SomeFunc()
{
    SomeEnum e = (SomeEnum)5;
}

Попробовав в другой раз, я получил этот метод расширения:

public static class EnumExtension
{
    public static int Max(this Enum enumType)
    {           
        return Enum.GetValues(enumType.GetType()).Cast<int>().Max();             
    }
}

class Program
{
    enum enum1 { one, two, second, third };
    enum enum2 { s1 = 10, s2 = 8, s3, s4 };
    enum enum3 { f1 = -1, f2 = 3, f3 = -3, f4 };

    static void Main(string[] args)
    {
        Console.WriteLine(enum1.one.Max());        
    }
}

При использовании последней функции не удалось получить максимальное значение.Использовать функцию "max" можно было бы.Нравится:

 class Program
    {
        enum enum1 { one, two, second, third };
        enum enum2 { s1 = 10, s2 = 8, s3, s4 };
        enum enum3 { f1 = -1, f2 = 3, f3 = -3, f4 };

        static void Main(string[] args)
        {
            TestMaxEnumValue(typeof(enum1));
            TestMaxEnumValue(typeof(enum2));
            TestMaxEnumValue(typeof(enum3));
        }

        static void TestMaxEnumValue(Type enumType)
        {
            Enum.GetValues(enumType).Cast<Int32>().ToList().ForEach(item =>
                Console.WriteLine(item.ToString()));

            int maxValue = Enum.GetValues(enumType).Cast<int>().Max();     
            Console.WriteLine("The max value of {0} is {1}", enumType.Name, maxValue);
        }
    }

В согласии с Мэтью Дж. Салливаном, для C#:

   Enum.GetValues(typeof(MyEnum)).GetUpperBound(0);

Я действительно не уверен, зачем кому-то понадобилось бы использовать:

   Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>().Last();

... Как дословно, с семантической точки зрения, это, кажется, не имеет такого большого смысла?(всегда хорошо иметь разные способы, но я не вижу пользы в последнем.)

Существуют методы для получения информации о перечисленных типах в System.Enum.

Итак, в проекте VB.Net в Visual Studio я могу ввести "System.Enum". и intellisense выдает всевозможные полезные функции.

Одним из методов, в частности, является System.Enum.getValues(), который возвращает массив перечисленных значений.Получив массив, вы должны быть в состоянии делать все, что подходит для ваших конкретных обстоятельств.

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

VB.Net фрагменты кода:

'''''''

Enum MattType
  zerothValue         = 0
  firstValue          = 1
  secondValue         = 2
  thirdValue          = 3
End Enum

'''''''

Dim iMax      As Integer

iMax = System.Enum.GetValues(GetType(MattType)).GetUpperBound(0)

MessageBox.Show(iMax.ToString, "Max MattType Enum Value")

'''''''

В F #, со вспомогательной функцией для преобразования перечисления в последовательность:

type Foo =
    | Fizz  = 3
    | Bang  = 2

// Helper function to convert enum to a sequence. This is also useful for iterating.
// stackoverflow.com/questions/972307/can-you-loop-through-all-enum-values-c
let ToSeq (a : 'A when 'A : enum<'B>) =
    Enum.GetValues(typeof<'A>).Cast<'B>()

// Get the max of Foo
let FooMax = ToSeq (Foo()) |> Seq.max   

Запускаю его...

> type Foo = | Fizz = 3 | Bang = 2
> val ToSeq : 'A -> seq<'B> when 'A : enum<'B>
> val FooMax : Foo = Fizz

Тот Самый when 'A : enum<'B> не требуется компилятору для определения, но требуется для любого использования toSeq, даже для допустимого перечисляемого типа.

Это можно использовать не при всех обстоятельствах, но я часто сам определяю максимальное значение:

enum Values {
  one,
  two,
  tree,
  End,
}

for (Values i = 0; i < Values.End; i++) {
  Console.WriteLine(i);
}

var random = new Random();
Console.WriteLine(random.Next((int)Values.End));

Конечно, это не сработает, когда вы используете пользовательские значения в перечислении, но часто это может быть простым решением.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top