Número total de elementos definidos en una enumeración

318

¿Cómo puedo obtener el número de elementos definidos en una enumeración?

Usuario SO
fuente

Respuestas:

430

Puede usar el método estático Enum.GetNamesque devuelve una matriz que representa los nombres de todos los elementos de la enumeración. La propiedad de longitud de esta matriz es igual al número de elementos definidos en la enumeración

var myEnumMemberCount = Enum.GetNames(typeof(MyEnum)).Length;
Kasper Holdum
fuente
1
De acuerdo ... aquí hay un enlace que encontré csharp411.com/c-count-items-in-an-enum
Usuario SO
8
También podría usar Enum.GetValues.
Xonatron
66
System.Enum.GetNames, si aún no incluye el espacio de nombres del sistema.
Brett Pennings
44
Así que me encontré con este problema nuevamente hoy; el truco de estilo C como se describe en otras respuestas a continuación aparece como problemático, pero tanto Enum.GetValues ​​como Enum.GetNames como se enumeran arriba parecen arriesgarse a asignar una matriz completamente nueva solo para obtener una longitud fija, lo que parece ... bueno horrible ¿Alguien sabe si este enfoque realmente incurre en una asignación dinámica? Si es así, para ciertos casos de uso, parece la solución más eficaz, si no la más flexible.
J Trana
174

La pregunta es:

¿Cómo puedo obtener el número de elementos definidos en una enumeración?

El número de "artículos" realmente podría significar dos cosas completamente diferentes. Considere el siguiente ejemplo.

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

¿Cuál es el número de "artículos" definidos en MyEnum?

¿Es el número de artículos 5? ( A` B` C` D` E)

¿O es 3? ( 1` 2` 3)

El número de nombres definidos en MyEnum(5) se puede calcular de la siguiente manera.

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

El número de valores definidos en MyEnum(3) se puede calcular de la siguiente manera.

var valuesCount = Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>().Distinct().Count();
Timothy Shields
fuente
2
Forma alternativa de escribir la última línea var valuesCount = ((MyEnum[])Enum.GetValues(typeof(MyEnum))).Distinct().Count();,.
Jeppe Stig Nielsen
3
No puedo pensar en ningún desarrollador que haya conocido en mi vida que afirme que tal enumeración contiene 3 elementos.
motoDrizzt
2
@motoDrizzt puede encontrar algo así en una enumeración de un controlador de impresora como Default = 1, A4 = 1, Portrate = 1, A4Portrait = 1, Landscape = 2, A4Landscape = 2, ...;).
shA.t
72

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

Matt Hamilton
fuente
77
Es más rápido usar el método GetNames.
Kasper Holdum
¿Deben almacenarse los resultados en una clase de utilidad?
djmj
14

Un ingenioso truco que vi en una respuesta C a esta pregunta, solo agregue un último elemento a la enumeración y úselo para decir cuántos elementos hay en la enumeración:

enum MyType {
  Type1,
  Type2,
  Type3,
  NumberOfTypes
}

En el caso de que esté definiendo un valor inicial distinto de 0, puede usar NumberOfTypes - Type1 para determinar el número de elementos.

No estoy seguro de si este método sería más rápido que usar Enum, y tampoco estoy seguro de si se consideraría la forma correcta de hacerlo, ya que tenemos Enum para averiguar esta información por nosotros.

Josh
fuente
1
esto es bueno ya que puedo hacer esto en XNA porque GetNames no está disponible allí
Thiago Valle
Genial truco, esto también sería más rápido que GetNames () porque no tiene que contarlos.
Jordan LaPrise
44
Tenga cuidado con el código que recorre las enumeraciones a través de foreach: ¡puede leer el final de sus matrices!
Michael Dorgan
44
Además, tenga cuidado con las enumeraciones que definen sus propios valores: a menudo uso enumeraciones para marcas de bits.
Matt Parkins
1
También tenga cuidado con los enlaces directos de enumeración a algunos controles
wpf
6

De las respuestas anteriores simplemente agregando código de muestra.

 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
fuente
5

Puede usar Enum.GetNames para devolver un IEnumerable de valores en su enumeración y luego .Cuenta el IEnumerable resultante.

GetNames produce el mismo resultado que GetValues ​​pero es más rápido.

Lucas Willett
fuente
5

Si te encuentras escribiendo la solución anterior con tanta frecuencia como yo, entonces podrías implementarla como genérica:

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
fuente
1

Estaba investigando esto justo ahora, y no estaba contento con la legibilidad de la solución actual. Si está escribiendo código de manera informal o en un proyecto pequeño, simplemente puede agregar otro elemento al final de su enumeración llamado "Longitud". De esta manera, solo necesita escribir:

var namesCount = (int)MyEnum.Length;

Por supuesto, si otros van a usar su código, o estoy seguro de que en muchas otras circunstancias que no se aplican a mí en este caso, esta solución puede ser desde desaconsejable hasta terrible.

EnergyWasRaw
fuente
2
Esto también se basa en la enumeración que comienza en 0 (el valor predeterminado, pero de ninguna manera está garantizado). Además, hace que el intellisense para el uso normal de enum sea muy confuso. Esta es casi siempre una idea terrible .
BradleyDotNET
2
Eso no tardó mucho :)
EnergyWasRaw
1
Interesante, supongo que nunca se sabe cuándo puede ocurrir algo mejor. Hice mi mejor intento de evitar mi propia solución, ¡pero lo encontré lo suficientemente interesante como para compartir!
EnergyWasRaw
1

Para Visual Basic:

[Enum].GetNames(typeof(MyEnum)).Lengthno funcionó conmigo, pero lo [Enum].GetNames(GetType(Animal_Type)).lengthhizo.

S22
fuente
¿Por qué el voto negativo? Esto solucionó mi problema, es la sintaxis correcta para VB, aunque la pregunta está etiquetada como c #, sigue siendo útil.
M Granja
2
Votos negativos probablemente porque la pregunta está etiquetada con C # y esta respuesta no mencionó que no estaba usando C #.
idbrii