Я думаю, что компилятор мог бы справиться с этим, вместо использования вызова Reflection. Ответ, который использовал метод времени компиляции для этой информации, получил бы мой положительный голос.
Palswim
Ответы:
214
Enum.GetValues (), кажется, возвращает значения по порядку, так что вы можете сделать что-то вроде этого:
// given this enum:publicenumFoo{Fizz=3,Bar=1,Bang=2}// this gets Fizzvar lastFoo =Enum.GetValues(typeof(Foo)).Cast<Foo>().Last();
редактировать
Для тех, кто не хочет читать комментарии: Вы также можете сделать это следующим образом:
var lastFoo =Enum.GetValues(typeof(Foo)).Cast<Foo>().Max();
... который будет работать, когда некоторые из ваших значений enum отрицательны.
Я била головой, думая, что это действительно тривиально, но было дано элегантное решение. Также, если вы хотите получить значение enum, используйте Convert.ToInt32 () впоследствии. Это для результатов Google.
jdelator
54
Если вы собираетесь использовать LINQ, почему бы не использовать Max (), который намного понятнее и не полагается на «кажется»?
Марк Гравелл
3
Это работает лучше, но только если значения перечисления не отрицательны, какими они могли бы быть.
ICR
4
Я тоже голосую за Макса (). Last () потерпит неудачу, если enum не отрицателен, смотрите здесь
AZ.
42
Я согласен с ответом Мэтта. Если вам нужны только значения min и max int, то вы можете сделать это следующим образом.
Согласно ответу Мэтта Гамильтона, я подумал о создании для него метода Extension.
Так ValueTypeне принят в качестве общего ограничения параметров типа, я не нашел лучший способ ограничить Tдо , Enumно ниже.
Любые идеи будут по достоинству оценены.
PS. пожалуйста, игнорируйте мою неявность VB, я люблю использовать VB таким образом, это сила VB, и поэтому я люблю VB.
Хоева, вот оно:
C #:
staticvoidMain(string[] args){MyEnum x =GetMaxValue<MyEnum>();//In newer versions of C# (7.3+)MyEnum y =GetMaxValueOld<MyEnum>();}publicstaticTEnumGetMaxValue<TEnum>()whereTEnum:Enum{returnEnum.GetValues(typeof(TEnum)).Cast<TEnum>().Max();}//When C# version is smaller than 7.3, use this:publicstaticTEnumGetMaxValueOld<TEnum>()whereTEnum:IComparable,IConvertible,IFormattable{Type type =typeof(TEnum);if(!type.IsSubclassOf(typeof(Enum)))thrownewInvalidCastException("Cannot cast '"+ type.FullName+"' to System.Enum.");return(TEnum)Enum.ToObject(type,Enum.GetValues(type).Cast<int>().Last());}enumMyEnum{ValueOne,ValueTwo}
VB:
PublicFunctionGetMaxValue _
(OfTEnumAs{IComparable,IConvertible,IFormattable})()AsTEnumDim type =GetType(TEnum)IfNot type.IsSubclassOf(GetType([Enum]))Then _
ThrowNewInvalidCastException _
("Cannot cast '"& type.FullName&"' to System.Enum.")Return[Enum].ToObject(type,[Enum].GetValues(type) _
.Cast(OfInteger).Last)EndFunction
вы также можете добавить «struct» к вашему where, так как это будет гарантировать, что это ValueType, но не ограничивать его перечислением. Это то, что я использую: где T: struct, IComparable, IFormattable
jdawiz
2
Вы можете обновить свой ответ. В C # 7.3 вы могли бы на самом деле сделать метод расширения, а также ограничиться типом Enum (вместо struct).
Нордес
Это не метод расширения, хотя. Но хороший полезный метод.
Рэй
14
Это немного nitpicky , но фактическое максимальное значение любого enumявляется Int32.MaxValue(при условии , что это enumпроисходит от int). Совершенно законно приводить любое Int32значение к любому enumнезависимо от того, действительно ли оно объявило члена с этим значением.
Допустимо:
enumSomeEnum{Fizz=42}publicstaticvoidSomeFunc(){SomeEnum e =(SomeEnum)5;}
У меня были случаи, когда установка переменной Integer на возвращаемое перечисление завершалась неудачно с несоответствием типов при вводе сумасшедшего значения, поэтому лучше вместо этого использовать Long (если вы лениво не улавливаете ошибку должным образом!).
AjV Jsy
9
После того, как попробовал в другой раз, я получил этот метод расширения:
Использование GetUpperBound возвращает мне счет (4, а не 40): MyEnum {a = 0, b = 10, c = 20, d = 30, e = 40}
alirobe
Хороший улов, я этого не заметил. Итак, эта версия отлично подходит для стандартных автоматических перечислений, но не для перечислений с пользовательскими значениями. Я думаю, что победителем остается мистер Гамильтон. :)
инженер
GetUpperBound хорош, когда ваш Enum имеет побитовые значения. (т.е. - 1, 2, 4, 8 и т. д.). Например, если вы писали модульный тест, вы бы хотели работать через цикл с таким количеством итераций: Math.Pow (2, Enum.GetValues (typeof (MyEnum)). GetUpperBound (0)).
WEFX
Что не так с Length (для количества значений в перечислении)? Проще лучше. (Не то чтобы это
отвечало
2
Существуют методы для получения информации о перечисляемых типах в System.Enum.
Итак, в проекте VB.Net в Visual Studio я могу напечатать «System.Enum». и intellisense воспитывает все виды доброты.
В частности, одним из методов является System.Enum.GetValues (), который возвращает массив перечисляемых значений. Получив массив, вы сможете делать все, что подходит для ваших конкретных обстоятельств.
В моем случае мои перечисляемые значения начинались с нуля и не пропускали никаких чисел, поэтому, чтобы получить максимальное значение для моего перечисления, мне просто нужно знать, сколько элементов было в массиве.
Не работает, когда в массиве есть пробелы. Это также работает только случайно, потому что индекс элемента оказывается равным значению, хранящемуся в этом индексе. GetUpperBound()извлекает максимально возможный индекс в массиве, возвращенном GetValues(), а не наибольшее значение, хранящееся в этом массиве.
JensG
2
В 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-cletToSeq(a :'A when 'A :enum<'B>)=Enum.GetValues(typeof<'A>).Cast<'B>()// Get the max of FooletFooMax=ToSeq(Foo())|>Seq.max
Запуск это ...
> Тип Foo = | Fizz = 3 | Взрыв = 2
> val ToSeq: 'A -> seq <' B> когда 'A: enum <' B>
> val FooMax: Foo = Fizz
when 'A : enum<'B>Не требуется компилятор для определения, но требуются для любого использования ToSeq, даже действительным перечислимого типа.
Его нельзя использовать при любых обстоятельствах, но я часто сам определяю максимальное значение:
enumValues{
one,
two,
tree,End,}for(Values i =0; i <Values.End; i++){Console.WriteLine(i);}var random =newRandom();Console.WriteLine(random.Next((int)Values.End));
Конечно, это не будет работать, когда вы используете пользовательские значения в перечислении, но часто это может быть простым решением.
Я использовал следующее, когда мне нужно минимальное и максимальное значения моего перечисления. Я просто установил минимальное значение, равное минимальному значению перечисления, и максимальное значение, равное максимальному значению перечисления, поскольку сами значения перечисления.
publicenumChannelMessageTypes:byte{Min=0x80,// Or could be: Min = NoteOffNoteOff=0x80,NoteOn=0x90,PolyKeyPressure=0xA0,ControlChange=0xB0,ProgramChange=0xC0,ChannelAfterTouch=0xD0,PitchBend=0xE0,Max=0xE0// Or could be: Max = PitchBend}// I use it like this to check if a ... is a channel message.if(...>=ChannelMessageTypes.Min||...<=ChannelMessages.Max){Console.WriteLine("Channel message received!");}
Ответы:
Enum.GetValues (), кажется, возвращает значения по порядку, так что вы можете сделать что-то вроде этого:
редактировать
Для тех, кто не хочет читать комментарии: Вы также можете сделать это следующим образом:
... который будет работать, когда некоторые из ваших значений enum отрицательны.
источник
Я согласен с ответом Мэтта. Если вам нужны только значения min и max int, то вы можете сделать это следующим образом.
Максимум:
Минимум:
источник
Согласно ответу Мэтта Гамильтона, я подумал о создании для него метода Extension.
Так
ValueType
не принят в качестве общего ограничения параметров типа, я не нашел лучший способ ограничитьT
до ,Enum
но ниже.Любые идеи будут по достоинству оценены.
PS. пожалуйста, игнорируйте мою неявность VB, я люблю использовать VB таким образом, это сила VB, и поэтому я люблю VB.
Хоева, вот оно:
C #:
VB:
источник
Это немного nitpicky , но фактическое максимальное значение любого
enum
являетсяInt32.MaxValue
(при условии , что этоenum
происходит отint
). Совершенно законно приводить любоеInt32
значение к любомуenum
независимо от того, действительно ли оно объявило члена с этим значением.Допустимо:
источник
После того, как попробовал в другой раз, я получил этот метод расширения:
источник
При использовании функции Last не удалось получить максимальное значение. Использовать функцию «макс» можно. Подобно:
источник
По согласованию с Мэтью Дж Салливаном, для C #:
Я действительно не уверен, почему кто-то хотел бы использовать:
... Как дословно, семантически говоря, это не имеет особого смысла? (всегда хорошо иметь разные способы, но я не вижу выгоды в последнем.)
источник
Существуют методы для получения информации о перечисляемых типах в System.Enum.
Итак, в проекте VB.Net в Visual Studio я могу напечатать «System.Enum». и intellisense воспитывает все виды доброты.
В частности, одним из методов является System.Enum.GetValues (), который возвращает массив перечисляемых значений. Получив массив, вы сможете делать все, что подходит для ваших конкретных обстоятельств.
В моем случае мои перечисляемые значения начинались с нуля и не пропускали никаких чисел, поэтому, чтобы получить максимальное значение для моего перечисления, мне просто нужно знать, сколько элементов было в массиве.
Фрагменты кода VB.Net:
источник
GetUpperBound()
извлекает максимально возможный индекс в массиве, возвращенномGetValues()
, а не наибольшее значение, хранящееся в этом массиве.В F # с помощью вспомогательной функции для преобразования перечисления в последовательность:
Запуск это ...
when 'A : enum<'B>
Не требуется компилятор для определения, но требуются для любого использования ToSeq, даже действительным перечислимого типа.источник
Его нельзя использовать при любых обстоятельствах, но я часто сам определяю максимальное значение:
Конечно, это не будет работать, когда вы используете пользовательские значения в перечислении, но часто это может быть простым решением.
источник
Я использовал следующее, когда мне нужно минимальное и максимальное значения моего перечисления. Я просто установил минимальное значение, равное минимальному значению перечисления, и максимальное значение, равное максимальному значению перечисления, поскольку сами значения перечисления.
источник