it-swarm-es.tech

¿Cómo enumero una enumeración en C #?

¿Cómo se puede enumerar una enum en C #?

P.ej. El siguiente código no se compila:

public enum Suit 
{
    Spades,
    Hearts,
    Clubs,
    Diamonds
}

public void EnumerateAllSuitsDemoMethod() 
{
    foreach (Suit suit in Suit) 
    {
        DoSomething(suit);
    }
}

Y da el siguiente error de compilación:

'Traje' es un 'tipo' pero se usa como una 'variable'

Falla en la palabra clave Suit, la segunda.

3435
Ian Boyd
foreach (Suit suit in (Suit[]) Enum.GetValues(typeof(Suit)))
{
}

Nota : La conversión a (Suit[]) no es estrictamente necesaria, pero hace que el código sea 0.5 ns más rápido.

4232
jop

Me parece que realmente desea imprimir los nombres de cada enumeración, en lugar de los valores. En cuyo caso Enum.GetNames() parece ser el enfoque correcto.

public enum Suits
{
    Spades,
    Hearts,
    Clubs,
    Diamonds,
    NumSuits
}

public void PrintAllSuits()
{
    foreach (string name in Enum.GetNames(typeof(Suits)))
    {
        System.Console.WriteLine(name);
    }
}

Por cierto, aumentar el valor no es una buena manera de enumerar los valores de una enumeración. Deberías hacer esto en su lugar.

Yo usaría Enum.GetValues(typeof(Suit)) en su lugar.

public enum Suits
{
    Spades,
    Hearts,
    Clubs,
    Diamonds,
    NumSuits
}

public void PrintAllSuits()
{
    foreach (var suit in Enum.GetValues(typeof(Suits)))
    {
        System.Console.WriteLine(suit.ToString());
    }
}
624
Haacked

Hice algunas extensiones para un fácil uso de la enumeración, tal vez alguien pueda usarlo ...

public static class EnumExtensions
{
    /// <summary>
    /// Gets all items for an enum value.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public static IEnumerable<T> GetAllItems<T>(this Enum value)
    {
        foreach (object item in Enum.GetValues(typeof(T)))
        {
            yield return (T)item;
        }
    }

    /// <summary>
    /// Gets all items for an enum type.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public static IEnumerable<T> GetAllItems<T>() where T : struct
    {
        foreach (object item in Enum.GetValues(typeof(T)))
        {
            yield return (T)item;
        }
    }

    /// <summary>
    /// Gets all combined items from an enum value.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    /// <example>
    /// Displays ValueA and ValueB.
    /// <code>
    /// EnumExample dummy = EnumExample.Combi;
    /// foreach (var item in dummy.GetAllSelectedItems<EnumExample>())
    /// {
    ///    Console.WriteLine(item);
    /// }
    /// </code>
    /// </example>
    public static IEnumerable<T> GetAllSelectedItems<T>(this Enum value)
    {
        int valueAsInt = Convert.ToInt32(value, CultureInfo.InvariantCulture);

        foreach (object item in Enum.GetValues(typeof(T)))
        {
            int itemAsInt = Convert.ToInt32(item, CultureInfo.InvariantCulture);

            if (itemAsInt == (valueAsInt & itemAsInt))
            {
                yield return (T)item;
            }
        }
    }

    /// <summary>
    /// Determines whether the enum value contains a specific value.
    /// </summary>
    /// <param name="value">The value.</param>
    /// <param name="request">The request.</param>
    /// <returns>
    ///     <c>true</c> if value contains the specified value; otherwise, <c>false</c>.
    /// </returns>
    /// <example>
    /// <code>
    /// EnumExample dummy = EnumExample.Combi;
    /// if (dummy.Contains<EnumExample>(EnumExample.ValueA))
    /// {
    ///     Console.WriteLine("dummy contains EnumExample.ValueA");
    /// }
    /// </code>
    /// </example>
    public static bool Contains<T>(this Enum value, T request)
    {
        int valueAsInt = Convert.ToInt32(value, CultureInfo.InvariantCulture);
        int requestAsInt = Convert.ToInt32(request, CultureInfo.InvariantCulture);

        if (requestAsInt == (valueAsInt & requestAsInt))
        {
            return true;
        }

        return false;
    }
}

La enumeración en sí debe estar decorada con el FlagsAttribute

[Flags]
public enum EnumExample
{
    ValueA = 1,
    ValueB = 2,
    ValueC = 4,
    ValueD = 8,
    Combi = ValueA | ValueB
}
311
bob

Algunas versiones de .NET framework no admiten Enum.GetValues. Aquí hay una buena solución de Ideas 2.0: Enum.GetValues ​​en Compact Framework :

public Enum[] GetValues(Enum enumeration)
{
    FieldInfo[] fields = enumeration.GetType().GetFields(BindingFlags.Static | BindingFlags.Public);
    Enum[] enumerations = new Enum[fields.Length];

    for (var i = 0; i < fields.Length; i++)
        enumerations[i] = (Enum) fields[i].GetValue(enumeration);

    return enumerations;
}

Al igual que con cualquier código que implique reflection , debe tomar medidas para garantizar que se ejecute solo una vez y que los resultados se almacenen en caché.

165
Ekevoo

¿Por qué nadie usa Cast<T>?

var suits = Enum.GetValues(typeof(Suit)).Cast<Suit>();

Ahí tienes IEnumerable<Suit>.

97
sircodesalot

Creo que esto es más eficiente que otras sugerencias porque GetValues() no se llama cada vez que tiene un bucle. También es más conciso. Y obtiene un error en tiempo de compilación, no una excepción de tiempo de ejecución si Suit no es enum.

EnumLoop<Suit>.ForEach((suit) => {
    DoSomethingWith(suit);
});

EnumLoop tiene esta definición completamente genérica:

class EnumLoop<Key> where Key : struct, IConvertible {
    static readonly Key[] arr = (Key[])Enum.GetValues(typeof(Key));
    static internal void ForEach(Action<Key> act) {
        for (int i = 0; i < arr.Length; i++) {
            act(arr[i]);
        }
    }
}
90
James

No obtendrás Enum.GetValues() en Silverlight.

Publicación original en el blog por Einar Ingebrigtsen :

public class EnumHelper
{
    public static T[] GetValues<T>()
    {
        Type enumType = typeof(T);

        if (!enumType.IsEnum)
        {
            throw new ArgumentException("Type '" + enumType.Name + "' is not an enum");
        }

        List<T> values = new List<T>();

        var fields = from field in enumType.GetFields()
                     where field.IsLiteral
                     select field;

        foreach (FieldInfo field in fields)
        {
            object value = field.GetValue(enumType);
            values.Add((T)value);
        }

        return values.ToArray();
    }

    public static object[] GetValues(Type enumType)
    {
        if (!enumType.IsEnum)
        {
            throw new ArgumentException("Type '" + enumType.Name + "' is not an enum");
        }

        List<object> values = new List<object>();

        var fields = from field in enumType.GetFields()
                     where field.IsLiteral
                     select field;

        foreach (FieldInfo field in fields)
        {
            object value = field.GetValue(enumType);
            values.Add(value);
        }

        return values.ToArray();
    }
}
72
Aubrey Taylor

Solo para agregar mi solución, que funciona en un marco compacto (3.5) y admite la comprobación de tipos en tiempo de compilación :

public static List<T> GetEnumValues<T>() where T : new() {
    T valueType = new T();
    return typeof(T).GetFields()
        .Select(fieldInfo => (T)fieldInfo.GetValue(valueType))
        .Distinct()
        .ToList();
}

public static List<String> GetEnumNames<T>() {
    return typeof (T).GetFields()
        .Select(info => info.Name)
        .Distinct()
        .ToList();
}

- Si alguien sabe cómo deshacerse de la T valueType = new T(), estaré encantado de ver una solución.

Una llamada se vería así:

List<MyEnum> result = Utils.GetEnumValues<MyEnum>();
54
Mallox

Creo que puedes usar

Enum.GetNames(Suit)
48
Tom Carr
public void PrintAllSuits()
{
    foreach(string suit in Enum.GetNames(typeof(Suits)))
    {
        Console.WriteLine(suit);
    }
}
46
Joshua Drake
foreach (Suit suit in Enum.GetValues(typeof(Suit))) { }

He escuchado rumores vagos de que esto es terriblemente lento. ¿Nadie sabe? - Orion Edwards, 15 de octubre de 2008 a la 1:31 7

Creo que el almacenamiento en caché de la matriz lo aceleraría considerablemente. Parece que cada vez se obtiene una nueva matriz (a través de la reflexión). Más bien:

Array enums = Enum.GetValues(typeof(Suit));
foreach (Suit suitEnum in enums) 
{
    DoSomething(suitEnum);
}

Eso es al menos un poco más rápido, ¿eh?

44
Limited Atonement

Tres maneras:

1. Enum.GetValues(type) //since .NET 1.1, not in silverlight or compact framewok
2. type.GetEnumValues() //only on .NET 4 and above
3. type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)) //works everywhere

No estoy seguro de por qué se introdujo GetEnumValues en la instancia de tipo, no es muy legible para mí.


Tener una clase de ayuda como Enum<T> es lo más fácil de leer y memorable para mí:

public static class Enum<T> where T : struct, IComparable, IFormattable, IConvertible
{
    public static IEnumerable<T> GetValues()
    {
        return (T[])Enum.GetValues(typeof(T));
    }

    public static IEnumerable<string> GetNames()
    {
        return Enum.GetNames(typeof(T));
    }
}

Ahora llamas:

Enum<Suit>.GetValues();
//or
Enum.GetValues(typeof(Suit)); //pretty consistent style

También se puede usar una especie de almacenamiento en caché si el rendimiento es importante, pero no espero que esto sea un problema en absoluto

public static class Enum<T> where T : struct, IComparable, IFormattable, IConvertible
{
    //lazily loaded
    static T[] values;
    static string[] names;

    public static IEnumerable<T> GetValues()
    {
        return values ?? (values = (T[])Enum.GetValues(typeof(T)));
    }

    public static IEnumerable<string> GetNames()
    {
        return names ?? (names = Enum.GetNames(typeof(T)));
    }
}
25
nawfal

En qué diablos voy a tirar mis dos peniques, solo mediante la combinación de las mejores respuestas, a través de una extensión muy simple.

public static class EnumExtensions
{
    /// <summary>
    /// Gets all items for an enum value.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public static IEnumerable<T> GetAllItems<T>(this T value) where T : Enum
    {
        return (T[])Enum.GetValues(typeof (T));
    }
}

Limpio simple y por el comentario de @ Jeppe-Stig-Nielsen rápido.

22
Darkside

Utilizo ToString (), luego divido y analizo la matriz de escupir en banderas.

[Flags]
public enum ABC {
   a = 1,
   b = 2,
   c = 4
};

public IEnumerable<ABC> Getselected (ABC flags)
{
   var values = flags.ToString().Split(',');
   var enums = values.Select(x => (ABC)Enum.Parse(typeof(ABC), x.Trim()));
   return enums;
}

ABC temp= ABC.a | ABC.b;
var list = getSelected (temp);
foreach (var item in list)
{
   Console.WriteLine(item.ToString() + " ID=" + (int)item);
}
21
Mickey Perlstein

Hay dos formas de iterar una Enum:

1. var values =  Enum.GetValues(typeof(myenum))
2. var values =  Enum.GetNames(typeof(myenum))

El primero le dará valores en forma en una matriz deobject, y el segundo le dará valores en forma de matriz deString.

Úselo en el bucle foreach como se muestra a continuación:

foreach(var value in values)
{
    //Do operations here
}
21
Kylo Ren

Si necesita velocidad y verificación de tipos en el tiempo de construcción y ejecución, este método auxiliar es mejor que usar LINQ para lanzar cada elemento:

public static T[] GetEnumValues<T>() where T : struct, IComparable, IFormattable, IConvertible
{
    if (typeof(T).BaseType != typeof(Enum))
    {
        throw new ArgumentException(string.Format("{0} is not of type System.Enum", typeof(T)));
    }
    return Enum.GetValues(typeof(T)) as T[];
}

Y puedes usarlo como a continuación:

static readonly YourEnum[] _values = GetEnumValues<YourEnum>();

Por supuesto que puede devolver IEnumerable<T>, pero eso no le compra nada aquí.

15
dmihailescu

No tengo la opinión de que esto es mejor, o incluso bueno, simplemente declarando otra solución.

Si los valores de enumeración van estrictamente de 0 a n - 1, una alternativa genérica:

public void EnumerateEnum<T>()
{
    int length = Enum.GetValues(typeof(T)).Length;
    for (var i = 0; i < length; i++)
    {
        var @enum = (T)(object)i;
    }
}

Si los valores de enumeración son contiguos y puede proporcionar el primer y último elemento de la enumeración, entonces:

public void EnumerateEnum()
{
    for (var i = Suit.Spade; i <= Suit.Diamond; i++)
    {
        var @enum = i;
    }
}

pero eso no es una enumeración estricta, solo hacer un bucle. El segundo método es mucho más rápido que cualquier otro enfoque, aunque ...

15
nawfal

aquí hay un ejemplo práctico de cómo crear opciones de selección para un DDL.

var resman = ViewModelResources.TimeFrame.ResourceManager;

ViewBag.TimeFrames = from MapOverlayTimeFrames timeFrame 
      in Enum.GetValues(typeof(MapOverlayTimeFrames))
      select new SelectListItem
      {
         Value = timeFrame.ToString(),
         Text = resman.GetString(timeFrame.ToString()) ?? timeFrame.ToString()
      };
12
jhilden
foreach (Suit suit in Enum.GetValues(typeof(Suit)))
{
}

(La respuesta aceptada actual tiene un elenco que no creo que sea necesario (aunque puedo estar equivocado).)

10
matt burns

Esta pregunta aparece en el Capítulo 10 de " C # Step by Step 2013 "

El autor utiliza un doble for-loop para iterar a través de un par de enumeradores (para crear un mazo de cartas completo):

class Pack
{
    public const int NumSuits = 4;
    public const int CardsPerSuit = 13;
    private PlayingCard[,] cardPack;

    public Pack()
    {
        this.cardPack = new PlayingCard[NumSuits, CardsPerSuit];
        for (Suit suit = Suit.Clubs; suit <= Suit.Spades; suit++)
        {
            for (Value value = Value.Two; value <= Value.Ace; value++)
            {
                cardPack[(int)suit, (int)value] = new PlayingCard(suit, value);
            }
        }
    }
}

En este caso, Suit y Value son enumeraciones:

enum Suit { Clubs, Diamonds, Hearts, Spades }
enum Value { Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King, Ace}

y PlayingCard es un objeto de tarjeta con una Suit y Value definidas:

class PlayingCard
{
    private readonly Suit suit;
    private readonly Value value;

    public PlayingCard(Suit s, Value v)
    {
        this.suit = s;
        this.value = v;
    }
}
9
Ross Gatih

Sé que es un poco desordenado, pero si eres fanático de los de una sola línea, aquí hay uno:

((Suit[])Enum.GetValues(typeof(Suit))).ToList().ForEach(i => DoSomething(i));
8
anar khalilov

¿Qué sucede si sabe que el tipo será una enum, pero no sabe cuál es el tipo exacto en el momento de la compilación?

public class EnumHelper
{
    public static IEnumerable<T> GetValues<T>()
    {
        return Enum.GetValues(typeof(T)).Cast<T>();
    }

    public static IEnumerable getListOfEnum(Type type)
    {
        MethodInfo getValuesMethod = typeof(EnumHelper).GetMethod("GetValues").MakeGenericMethod(type);
        return (IEnumerable)getValuesMethod.Invoke(null, null);
    }
}

El método getListOfEnum usa la reflexión para tomar cualquier tipo de enumeración y devuelve una IEnumerable de todos los valores de enumeración.

Uso:

Type myType = someEnumValue.GetType();

IEnumerable resultEnumerable = getListOfEnum(myType);

foreach (var item in resultEnumerable)
{
    Console.WriteLine(String.Format("Item: {0} Value: {1}",item.ToString(),(int)item));
}
7
Slappywag

Una forma simple y genérica de convertir una enumeración a algo con lo que puedes interactuar:

public static Dictionary<int, string> ToList<T>() where T : struct
{
   return ((IEnumerable<T>)Enum
       .GetValues(typeof(T)))
       .ToDictionary(
           item => Convert.ToInt32(item),
           item => item.ToString());
}

Y entonces:

var enums = EnumHelper.ToList<MyEnum>();
7
Gabriel

Agrega el método public static IEnumerable<T> GetValues<T>() a tu clase, como

public static IEnumerable<T> GetValues<T>()
{
    return Enum.GetValues(typeof(T)).Cast<T>();
}

llama y pasa tu enum, ahora puedes iterar a través de foreach

 public static void EnumerateAllSuitsDemoMethod()
 {
     // custom method
     var foos = GetValues<Suit>(); 
     foreach (var foo in foos)
     {
         // Do something
     }
 }
4
MUT

Los tipos enum se llaman "tipos de enumeración" no porque sean contenedores que "enumeren" valores (que no lo son), sino porque están definidos por enumerando los valores posibles para una variable de ese tipo.

(En realidad, eso es un poco más complicado que eso: se considera que los tipos de enumeración tienen un tipo entero "subyacente", lo que significa que cada valor de enumeración corresponde a un valor entero (esto suele ser implícito, pero se puede especificar manualmente). C # fue diseñado de manera que pueda incluir any integer de ese tipo en la variable enum, incluso si no es un valor "con nombre".

El método System.Enum.GetNames se puede usar para recuperar una matriz de cadenas que son los nombres de los valores de enumeración, como sugiere el nombre.

EDITAR: Debería haber sugerido el método System.Enum.GetValues en su lugar. Ups.

1
Emily Chen

También puede enlazar a los miembros públicos estáticos de la enumeración directamente mediante la reflexión:

typeof(Suit).GetMembers(BindingFlags.Public | BindingFlags.Static)
    .ToList().ForEach(x => DoSomething(x.Name));
0
Termininja