Número total de itens definidos em uma enumeração

318

Como posso obter o número de itens definido em uma enumeração?

Usuário SO
fonte

Respostas:

430

Você pode usar o método estático Enum.GetNamesque retorna uma matriz que representa os nomes de todos os itens na enumeração. A propriedade length dessa matriz é igual ao número de itens definidos na enumeração

var myEnumMemberCount = Enum.GetNames(typeof(MyEnum)).Length;
Kasper Holdum
fonte
1
Concordado ... aqui está um link que eu encontrei csharp411.com/c-count-items-in-an-enum
SO User
8
Também pode usar Enum.GetValues.
Xonatron #
6
System.Enum.GetNames, se você ainda não estiver incluindo o espaço para nome System.
Brett Pennings
4
Então, acabei de encontrar esse problema novamente hoje; o truque do estilo C, conforme descrito em outras respostas abaixo, está listado como problemático, mas Enum.GetValues ​​e Enum.GetNames, conforme listado acima, parecem correr o risco de alocar uma matriz totalmente nova apenas para obter um comprimento fixo, o que parece ... bem horrível. Alguém sabe se essa abordagem realmente gera alocação dinâmica? Nesse caso, para certos casos de uso, parece de longe a solução com melhor desempenho, se não a mais flexível.
perfil completo de J Trana
174

A questão é:

Como posso obter o número de itens definido em uma enumeração?

O número de "itens" pode realmente significar duas coisas completamente diferentes. Considere o seguinte exemplo.

enum MyEnum
{
    A = 1,
    B = 2,
    C = 1,
    D = 3,
    E = 2
}

Qual é o número de "itens" definido em MyEnum?

O número de itens é 5? ( A, B, C, D, E)

Ou é 3? ( 1, 2, 3)

O número de nomes definidos em MyEnum(5) pode ser calculado da seguinte forma.

var namesCount = Enum.GetNames(typeof(MyEnum)).Length;

O número de valores definidos em MyEnum(3) pode ser calculado da seguinte forma.

var valuesCount = Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>().Distinct().Count();
Timothy Shields
fonte
2
Maneira alternativa de escrever a última linha var valuesCount = ((MyEnum[])Enum.GetValues(typeof(MyEnum))).Distinct().Count();,.
Jeppe Stig Nielsen
3
Não consigo pensar em nenhum desenvolvedor que já conheci na minha vida que afirmasse que essa enumeração contém 3 itens.
motoDrizzt
2
@motoDrizzt, você pode encontrar algo parecido no enum de um driver de impressora como Default = 1, A4 = 1, Portrate = 1, A4Portrait = 1, Landscape = 2, A4Landscape = 2, ...;).
shA.t
72

Enum.GetValues (typeof (MyEnum)). Length;

Matt Hamilton
fonte
7
É mais rápido usar o método GetNames.
Kasper Holdum
Os resultados devem ser armazenados em cache em uma classe de utilitário?
djmj
14

Um truque bacana que eu vi na resposta C a essa pergunta, basta adicionar um último elemento ao enum e usá-lo para dizer quantos elementos estão no enum:

enum MyType {
  Type1,
  Type2,
  Type3,
  NumberOfTypes
}

No caso de você definir um valor inicial diferente de 0, você pode usar NumberOfTypes - Type1 para verificar o número de elementos.

Não tenho certeza se esse método seria mais rápido do que usar o Enum, e também não tenho certeza se seria considerado a maneira correta de fazer isso, pois temos o Enum para verificar essas informações para nós.

Josh
fonte
1
isso é bom desde que eu posso fazer isso em XNA porque GetNames não está disponível lá
Thiago Valle
Truque legal, isso também seria mais rápido que GetNames () porque não precisa contá-los.
Jordan LaPrise
4
Cuidado com o código que percorre enumerações via foreach - você pode ler o final de suas matrizes!
Michael Dorgan
4
Além disso, cuidado com as enumerações que definem seus próprios valores - costumo usar enumerações para sinalizadores de bits.
Matt Parkins 26/03
1
Também cuidado de ligações enum directos para alguns controlos WPF tais como caixa de combinação e listagem
mcy
6

Das respostas anteriores apenas adicionando amostra de código.

 class Program
    {
        static void Main(string[] args)
        {
            int enumlen = Enum.GetNames(typeof(myenum)).Length;
            Console.Write(enumlen);
            Console.Read();
        }
        public enum myenum
        {
            value1,
            value2
        }
    }
jvanderh
fonte
5

Você pode usar Enum.GetNames para retornar um IEnumerable de valores na sua enumeração e, em seguida, contar o IEnumerable resultante.

GetNames produz praticamente o mesmo resultado que GetValues, mas é mais rápido.

Lucas Willett
fonte
5

Se você estiver escrevendo a solução acima tantas vezes quanto eu, poderá implementá-la como um genérico:

public static int GetEnumEntries<T>() where T : struct, IConvertible 
{
    if (!typeof(T).IsEnum)
        throw new ArgumentException("T must be an enumerated type");

    return Enum.GetNames(typeof(T)).Length;
}
Matt Parkins
fonte
1

Eu estava analisando isso agora e não estava satisfeito com a legibilidade da solução atual. Se você estiver escrevendo código informalmente ou em um projeto pequeno, basta adicionar outro item ao final da sua enumeração chamado "Comprimento". Dessa forma, você só precisa digitar:

var namesCount = (int)MyEnum.Length;

É claro que se outras pessoas usarem seu código - ou tenho certeza de que em muitas outras circunstâncias que não se aplicavam a mim neste caso - essa solução pode estar em qualquer lugar, desde mal aconselhado até terrível.

EnergyWasRaw
fonte
2
Isso também depende da enumeração iniciando em 0 (o padrão, mas de forma alguma garantida). Além disso, torna o intellisense para uso normal de enum muito confuso. Essa quase sempre é uma péssima idéia.
22414 BradleyDotNET
2
Isso não demorou muito :) :)
EnergyWasRaw
1
Interessante, suponho que você nunca saiba quando algo melhor pode acontecer. Fiz minha melhor tentativa de evitar minha própria solução, mas achei interessante o suficiente para compartilhar!
EnergyWasRaw
1

Para o Visual Basic:

[Enum].GetNames(typeof(MyEnum)).Lengthnão funcionou comigo, mas [Enum].GetNames(GetType(Animal_Type)).lengthfuncionou.

S22
fonte
Por que o voto negativo? Isso corrigiu o meu problema, é a sintaxe correta para o VB, mesmo que a pergunta esteja marcada como c #, ainda útil.
M Granja
2
Votos negativos provavelmente porque a pergunta está marcada com C # e esta resposta não mencionou que não estava usando C #.
Idbrii