Eu pensaria que o compilador poderia lidar com isso, em vez de usar uma chamada de reflexão. Uma resposta que usasse um método em tempo de compilação para essas informações receberia meu voto positivo.
palswim
Respostas:
214
Enum.GetValues () parece retornar os valores em ordem, para que você possa fazer algo assim:
// given this enum:publicenumFoo{Fizz=3,Bar=1,Bang=2}// this gets Fizzvar lastFoo =Enum.GetValues(typeof(Foo)).Cast<Foo>().Last();
Editar
Para aqueles que não desejam ler os comentários: Você também pode fazer o seguinte:
var lastFoo =Enum.GetValues(typeof(Foo)).Cast<Foo>().Max();
... que funcionará quando alguns de seus valores de enumeração forem negativos.
Eu estava batendo na minha cabeça, pensando que isso era realmente um rival, mas uma solução elegante foi dada. Além disso, se você deseja obter o valor da enumeração, use Convert.ToInt32 () posteriormente. Isto é para os resultados do google.
jdelator
53
Se você usar o LINQ, por que não usar Max (), que é muito mais claro e não depende de "parece"?
Marc Gravell
3
Ele tem um desempenho melhor, mas somente se os valores da enumeração não forem negativos, o que poderiam ser.
ICR
4
Também voto em Max (). O Last () falharia se o enum não fosse negativo, veja aqui
AZ.
41
Eu concordo com a resposta de Matt. Se você precisar apenas de valores mínimo e máximo int, poderá fazê-lo da seguinte maneira.
De acordo com a resposta de Matt Hamilton, pensei em criar um método de extensão para ele.
Como ValueTypenão é aceito como uma restrição de parâmetro de tipo genérico, não encontrei uma maneira melhor de restringir TaEnum , mas o seguinte.
Qualquer idéia seria realmente apreciada.
PS. por favor, ignore minha implicitude VB, eu amo usar VB dessa maneira, essa é a força do VB e é por isso que eu amo VB.
Howeva, aqui está:
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
você também pode adicionar "struct" para o seu onde, como isso irá garantir que ele é um ValueType, mas não restringi-lo a Enum Isto é o que eu uso: onde T: struct, IComparable, IFormattable
jdawiz
2
Você pode atualizar sua resposta. No C # 7.3, você poderia realmente executar o método de extensão e também restringir ao tipo Enum (em vez de struct).
Nordes
Este não é um método de extensão . Mas um bom método de utilidade.
Ray
14
Isso é um pouco complicado, mas o valor máximo real de qualquer um enumé Int32.MaxValue(assumindo que seja enumderivado de int). É perfeitamente legal converter qualquer Int32valor para qualquer um, enumindependentemente de ter ou não declarado um membro com esse valor.
Legal:
enumSomeEnum{Fizz=42}publicstaticvoidSomeFunc(){SomeEnum e =(SomeEnum)5;}
Já tive casos em que a definição de uma variável Integer para uma enum retornada falha com a incompatibilidade de tipo quando um valor louco é fornecido, por isso é melhor usar um Long (se você não estiver prendendo o erro corretamente!).
AJV JSY
9
Depois de tentar outra vez, obtive este método de extensão:
... Como palavra por palavra, semanticamente falando, não parece fazer tanto sentido? (sempre bom ter maneiras diferentes, mas não vejo o benefício no último.)
Usar GetUpperBound retorna uma contagem (4, não 40) para mim: MyEnum {a = 0, b = 10, c = 20, d = 30, e = 40}
alirobe
Boa captura, eu não tinha notado isso. OK, então esta versão é ótima para enumerações automáticas padrão, mas não para enumerações com valores personalizados. Acho que o vencedor continua sendo o senhor Hamilton. :)
Engenheiro
GetUpperBound é bom quando seu Enum possui valores bit a bit. (ie - 1, 2, 4, 8, etc). Por exemplo, se você estivesse escrevendo um teste de unidade, desejaria trabalhar com um loop com muitas iterações: Math.Pow (2, Enum.GetValues (typeof (MyEnum)). GetUpperBound (0)).
WEFX 18/08/19
O que há de errado com Comprimento (para o número de valores na enumeração)? Mais simples é melhor. (Não que isso responde à pergunta original.)
Ian Goldby
2
Existem métodos para obter informações sobre tipos enumerados em System.Enum.
Portanto, em um projeto VB.Net no Visual Studio, posso digitar "System.Enum". e o intellisense traz todo tipo de bondade.
Um método em particular é System.Enum.GetValues (), que retorna uma matriz dos valores enumerados. Depois de obter a matriz, você poderá fazer o que for apropriado para suas circunstâncias particulares.
No meu caso, meus valores enumerados começaram em zero e não saltaram nenhum número; portanto, para obter o valor máximo da minha enumeração, só preciso saber quantos elementos estavam na matriz.
Não funciona quando a matriz tem lacunas. Também funciona apenas por acidente, porque o índice do elemento é igual ao valor armazenado nesse índice. GetUpperBound()recupera o índice mais alto possível na matriz retornada por GetValues(), não o valor mais alto armazenado dentro dessa matriz.
JensG 01/06/19
2
No F #, com uma função auxiliar para converter o enum em uma sequência:
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
Executando ...
> tipo Foo = | Fizz = 3 | Bang = 2
> val ToSeq: 'A -> seq <' B> quando 'A: enum <' B>
> val FooMax: Foo = Fizz
O when 'A : enum<'B>não é exigido pelo compilador para a definição, mas é necessário para qualquer uso do ToSeq, mesmo por um tipo de enumeração válido.
Não é utilizável em todas as circunstâncias, mas geralmente eu mesmo defino o valor máximo:
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));
Obviamente, isso não funcionará quando você usar valores personalizados em uma enumeração, mas geralmente pode ser uma solução fácil.
Usei o seguinte quando precisei dos valores mínimo e máximo da minha enumeração. Acabei de definir um mínimo igual ao valor mais baixo da enumeração e um valor máximo igual ao valor mais alto na enumeração, já que os próprios valores da enumeração.
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!");}
Respostas:
Enum.GetValues () parece retornar os valores em ordem, para que você possa fazer algo assim:
Editar
Para aqueles que não desejam ler os comentários: Você também pode fazer o seguinte:
... que funcionará quando alguns de seus valores de enumeração forem negativos.
fonte
Eu concordo com a resposta de Matt. Se você precisar apenas de valores mínimo e máximo int, poderá fazê-lo da seguinte maneira.
Máximo:
Mínimo:
fonte
De acordo com a resposta de Matt Hamilton, pensei em criar um método de extensão para ele.
Como
ValueType
não é aceito como uma restrição de parâmetro de tipo genérico, não encontrei uma maneira melhor de restringirT
aEnum
, mas o seguinte.Qualquer idéia seria realmente apreciada.
PS. por favor, ignore minha implicitude VB, eu amo usar VB dessa maneira, essa é a força do VB e é por isso que eu amo VB.
Howeva, aqui está:
C #:
VB:
fonte
Isso é um pouco complicado, mas o valor máximo real de qualquer um
enum
éInt32.MaxValue
(assumindo que sejaenum
derivado deint
). É perfeitamente legal converter qualquerInt32
valor para qualquer um,enum
independentemente de ter ou não declarado um membro com esse valor.Legal:
fonte
Depois de tentar outra vez, obtive este método de extensão:
fonte
Use a função Last não pôde obter o valor máximo. Use a função "max" poderia. Gostar:
fonte
De acordo com Matthew J Sullivan, para C #:
Eu realmente não sei por que alguém iria querer usar:
... Como palavra por palavra, semanticamente falando, não parece fazer tanto sentido? (sempre bom ter maneiras diferentes, mas não vejo o benefício no último.)
fonte
Existem métodos para obter informações sobre tipos enumerados em System.Enum.
Portanto, em um projeto VB.Net no Visual Studio, posso digitar "System.Enum". e o intellisense traz todo tipo de bondade.
Um método em particular é System.Enum.GetValues (), que retorna uma matriz dos valores enumerados. Depois de obter a matriz, você poderá fazer o que for apropriado para suas circunstâncias particulares.
No meu caso, meus valores enumerados começaram em zero e não saltaram nenhum número; portanto, para obter o valor máximo da minha enumeração, só preciso saber quantos elementos estavam na matriz.
Fragmentos de código VB.Net:
fonte
GetUpperBound()
recupera o índice mais alto possível na matriz retornada porGetValues()
, não o valor mais alto armazenado dentro dessa matriz.No F #, com uma função auxiliar para converter o enum em uma sequência:
Executando ...
O
when 'A : enum<'B>
não é exigido pelo compilador para a definição, mas é necessário para qualquer uso do ToSeq, mesmo por um tipo de enumeração válido.fonte
Não é utilizável em todas as circunstâncias, mas geralmente eu mesmo defino o valor máximo:
Obviamente, isso não funcionará quando você usar valores personalizados em uma enumeração, mas geralmente pode ser uma solução fácil.
fonte
Usei o seguinte quando precisei dos valores mínimo e máximo da minha enumeração. Acabei de definir um mínimo igual ao valor mais baixo da enumeração e um valor máximo igual ao valor mais alto na enumeração, já que os próprios valores da enumeração.
fonte