Como você pode enumerar um enum
em c #?
Por exemplo, o seguinte código não compila:
public enum Suit
{
Spades,
Hearts,
Clubs,
Diamonds
}
public void EnumerateAllSuitsDemoMethod()
{
foreach (Suit suit in Suit)
{
DoSomething(suit);
}
}
E fornece o seguinte erro em tempo de compilação:
'Suit' é um 'tipo', mas é usado como uma 'variável'
Falha na Suit
palavra - chave, a segunda.
Respostas:
Nota : A conversão para
(Suit[])
não é estritamente necessária, mas torna o código 0,5 ns mais rápido .fonte
enum.GetValues
. Você precisa usar a reflexão neste caso.enum E {A = 0, B = 0}
.Enum.GetValues
resulta em dois valores sendo retornados, embora sejam os mesmos.E.A == E.B
é verdade, então não há distinção. Se você quiser nomes individuais, deve procurarEnum.GetNames
.Distinct
extensão do Linq (desde o .NET 3.5)foreach (var suit in ((Suit[])Enum.GetValues(typeof(Suit))).Distinct()) { }
.var
para o tipo. O compilador tornará a variável um emObject
vez da enumeração. Liste o tipo de enum explicitamente.Parece-me que você realmente deseja imprimir os nomes de cada enumeração, e não os valores. Nesse caso,
Enum.GetNames()
parece ser a abordagem correta.A propósito, incrementar o valor não é uma boa maneira de enumerar os valores de uma enumeração. Você deve fazer isso.
Eu usaria em seu
Enum.GetValues(typeof(Suit))
lugar.fonte
Enum.GetValues(typeof(Suits)).OfType<Suits>().ToArray()
. Nesse caso, eu posso iterar a matriz deSuits
itens de enumeração, não seqüências de caracteres.Suits suit in Enum.GetValues(typeof(Suits))
?Fiz algumas extensões para facilitar o uso de enum. Talvez alguém possa usá-lo ...
A enum em si deve ser decorada com o FlagsAttribute :
fonte
Algumas versões da estrutura .NET não suportam
Enum.GetValues
. Aqui está uma boa solução alternativa do Ideas 2.0: Enum.GetValues no Compact Framework :Como em qualquer código que envolve reflexão , você deve executar etapas para garantir que seja executado apenas uma vez e que os resultados sejam armazenados em cache.
fonte
return type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)).Cast<Enum>();
Use
Cast<T>
:Lá vai você
IEnumerable<Suit>
.fonte
from
cláusula e noforeach
declarador do cabeçalho.Eu acho que isso é mais eficiente do que outras sugestões, porque
GetValues()
não é chamado toda vez que você tem um loop. Também é mais conciso. E você recebe um erro em tempo de compilação, não uma exceção de tempo de execução, seSuit
não for umenum
.EnumLoop
tem esta definição completamente genérica:fonte
EnumLoop
com algum tipo que não seja enum, ele será compilado corretamente, mas lançará uma exceção no tempo de execução.Você não entra
Enum.GetValues()
no Silverlight .Postagem original do blog de Einar Ingebrigtsen :
fonte
where T: Enum
Minha solução funciona no .NET Compact Framework (3.5) e oferece suporte à verificação de tipo em tempo de compilação :
T valueType = new T()
, ficaria feliz em ver uma solução.Uma chamada ficaria assim:
fonte
T valueType = default(T)
?new()
T
. Além disso, você não precisanew T()
, você pode selecionar apenas os campos estáticos sozinho e fazer.GetValue(null)
. Veja a resposta de Aubrey.where T: Enum
Eu acho que você pode usar
fonte
fonte
Eu acho que o cache da matriz aceleraria consideravelmente. Parece que você está obtendo uma nova matriz (através da reflexão) sempre. Em vez:
Isso é pelo menos um pouco mais rápido, ja?
fonte
Três caminhos:
Enum.GetValues(type)
// Desde o .NET 1.1, não no Silverlight ou no .NET Compact Frameworktype.GetEnumValues()
// Somente no .NET 4 e acimatype.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null))
// Funciona em qualquer lugarNão sei por que
GetEnumValues
foi introduzido nas instâncias de tipo. Não é muito legível para mim.Ter uma classe auxiliar como
Enum<T>
é o mais legível e memorável para mim:Agora você liga para:
Também é possível usar algum tipo de cache se o desempenho for importante, mas não espero que isso seja um problema.
fonte
Apenas combinando as respostas principais, juntei uma extensão muito simples:
É limpo, simples e, pelo comentário de @ Jeppe-Stig-Nielsen, rápido.
fonte
where T: Enum
Existem duas maneiras de iterar um
Enum
:O primeiro fornecerá valores em forma em uma matriz de **
object
** s, e o segundo fornecerá valores em forma de uma matriz de **String
** s.Use-o em um
foreach
loop como abaixo:fonte
Eu uso ToString (), em seguida, dividir e analisar a matriz cuspir em sinalizadores.
fonte
Não acredito que isso seja melhor ou até bom. Estou apenas afirmando mais uma solução.
Se os valores de enum variam estritamente de 0 a n - 1, uma alternativa genérica é:
Se os valores da enumeração forem contíguos e você puder fornecer o primeiro e o último elemento da enumeração, então:
Mas isso não é estritamente enumerado, apenas repetido. O segundo método é muito mais rápido do que qualquer outra abordagem ...
fonte
Se você precisar de verificação de velocidade e tipo no tempo de compilação e execução, esse método auxiliar é melhor do que usar o LINQ para converter cada elemento:
E você pode usá-lo como abaixo:
Claro que você pode voltar
IEnumerable<T>
, mas isso não lhe comprará nada aqui.fonte
where T: Enum
Aqui está um exemplo prático de criação de opções de seleção para uma DDL :
fonte
(A resposta atual aceita tem um elenco que eu acho que não é necessário (embora eu possa estar errado).)
fonte
Esta pergunta aparece no capítulo 10 do " C # Step by Step 2013 "
O autor usa um loop for duplo para iterar através de um par de enumeradores (para criar um baralho completo de cartas):
Nesse caso,
Suit
eValue
são ambas as enumerações:e
PlayingCard
é um objeto de cartão com um definidoSuit
eValue
:fonte
Eu sei que é um pouco bagunçado, mas se você é fã de one-liners, aqui está um:
fonte
E se você souber que o tipo será um
enum
, mas não souber qual é o tipo exato no momento da compilação?O método
getListOfEnum
usa reflexão para obter qualquer tipo de enumeração e retorna umIEnumerable
de todos os valores de enumeração.Uso:
fonte
Uma maneira simples e genérica de converter uma enumeração em algo que você pode interagir:
E depois:
fonte
Dictionary
não é uma boa ideia: se vocêEnum
gostaenum E { A = 0, B = 0 }
, o valor 0 é adicionado 2 vezes, gerando umArgumentException
(você não pode adicionar o mesmoKey
emDictionary
2 ou mais vezes!).Dictionary<,>
partir de um método chamadoToList
? Também porque não voltarDictionary<T, string>
?Adicione método
public static IEnumerable<T> GetValues<T>()
à sua classe, como:Ligue e passe seu enum. Agora você pode iterar usando
foreach
:fonte
enum
Os tipos são chamados de "tipos de enumeração" não porque são contêineres que "enumeram" valores (que não são), mas porque são definidos pela enumeração dos valores possíveis para uma variável desse tipo.(Na verdade, isso é um pouco mais complicado do que isso - os tipos de enum são considerados como tendo um tipo inteiro "subjacente", o que significa que cada valor de enum corresponde a um valor inteiro (isso geralmente é implícito, mas pode ser especificado manualmente). de uma maneira que você possa encher qualquer inserir número inteiro desse tipo na variável enum, mesmo que não seja um valor "nomeado".)
O método System.Enum.GetNames pode ser usado para recuperar uma matriz de seqüências de caracteres que são os nomes dos valores de enumeração, como o nome sugere.
Edição: deveria ter sugerido o método System.Enum.GetValues . Opa
fonte
GetNames
método retorna, de fato, uma matriz de cadeias de caracteres, mas o OP requer um enumerador através dos valores.Eu tentei de várias maneiras e obtive o resultado deste código:
Para obter uma lista de int de uma enumeração, use o seguinte. Funciona!
fonte
Também é possível vincular diretamente aos membros estáticos públicos da enum usando reflexão:
fonte
Se você tem:
Este:
Saída:
fonte
Maneira genérica de LINQ :
Uso:
fonte