Pregunta

¿Cómo se puede enumerar una enum 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 en tiempo de compilación:

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

Falla en el Suit palabra clave, la segunda.

¿Fue útil?

Solución

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

Nota:El elenco a (Suit[]) no es estrictamente necesario, pero hace que el código sea 0,5 ns más rápido.

Otros consejos

Me parece que realmente quieres imprimir los nombres de cada enumeración, en lugar de los valores.En ese 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, incrementar el valor no es una buena forma de enumerar los valores de una enumeración.Deberías hacer esto en su lugar.

yo usaría Enum.GetValues(typeof(Suit)) en cambio.

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

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

Hice algunas extensiones para facilitar el uso de la enumeración, tal vez alguien pueda usarlas...

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 Atributo Banderas

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

Algunas versiones de .NET framework no son compatibles Enum.GetValues.Aquí hay una buena solución de Ideas 2.0:Enum.GetValues ​​en marco compacto:

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;
}

Como ocurre con cualquier código que involucre reflexión, debe tomar medidas para asegurarse de que se ejecute solo una vez y que los resultados se almacenen en caché.

¿Por qué nadie usa Cast<T>?

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

Ahí tienes IEnumerable<Suit>.

Creo que esto es más eficiente que otras sugerencias porque GetValues() no se llama cada vez que tienes un bucle.También es más conciso.Y obtienes un error en tiempo de compilación, no una excepción en tiempo de ejecución, si Suit no es un 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]);
        }
    }
}

no lo conseguirás Enum.GetValues() en Luz plateada.

Publicación original del blog de 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();
    }
}

Solo para agregar mi solución, que funciona en un marco compacto (3.5) y admite la verificació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 del T valueType = new T(), Me encantaría ver una solución.

Una llamada se vería así:

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

creo que puedes usar

Enum.GetNames(Suit)
public void PrintAllSuits()
{
    foreach(string suit in Enum.GetNames(typeof(Suits)))
    {
        Console.WriteLine(suit);
    }
}
foreach (Suit suit in Enum.GetValues(typeof(Suit))) { }

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

Creo que almacenar en caché la matriz lo aceleraría considerablemente.Parece que obtienes una nueva matriz (a través de la reflexión) cada vez.Bastante:

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

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

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é fue GetEnumValues introducido en una instancia de tipo, no es muy legible para mí.


Tener una clase de ayuda como Enum<T> es lo que es más legible 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 utilizar 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)));
    }
}

¿En qué diablos arrojaré mis dos peniques? Simplemente combinando las respuestas principales obtengo 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 según el comentario de @Jeppe-Stig-Nielsen, rápido.

Utilizo ToString() y luego divido y analizo la matriz de saliva 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);
}

Hay dos maneras de iterar un Enum:

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

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

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

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

No creo que esto sea mejor, ni siquiera bueno, solo expongo otra solución más.

Si los valores de enumeración varían 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 un bucle.Sin embargo, el segundo método es mucho más rápido que cualquier otro enfoque...

Si necesita verificación de velocidad y tipos en tiempo de compilación y ejecución, este método auxiliar es mejor que usar LINQ para convertir 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 se muestra a continuación:

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

Por supuesto que puedes regresar IEnumerable<T>, pero eso no te compra nada aquí.

Aquí hay un ejemplo funcional 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()
      };
foreach (Suit suit in Enum.GetValues(typeof(Suit)))
{
}

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

Esta pregunta aparece en el Capítulo 10 de "C# Paso a Paso 2013"

El autor utiliza un bucle for doble para recorrer un par de enumeradores (para crear una baraja de cartas completa):

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 ambas 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 un definido Suit y Value:

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

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

Sé que es un poco complicado, pero si eres fanático de las frases ingeniosas, aquí tienes una:

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

¿Qué pasa si sabes que el tipo será un enum, pero ¿no sabes 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 un 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));
}

Una forma simple y genérica de convertir una enumeración en algo con lo que puedas 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 luego:

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

Agregar 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 enumeración, ahora puedes iterar a través de ella usando foreach

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

enum Los tipos se denominan "tipos de enumeración" no porque sean contenedores que "enumeran" 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 tal manera que pudieras rellenar cualquier entero de ese tipo en la variable enum, incluso si no es un valor "nombrado").

El Método System.Enum.GetNames se puede utilizar 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 Sistema.Enum.GetValues método en su lugar.Ups.

También puede vincularse 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));

Intente usar foreach (elemento var en enum.getValues ​​(typeof (trajes)))

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top