[c#] ¿Cómo iterar sobre una enumeración?


Answers

Me parece que realmente desea imprimir los nombres de cada enumeración, en lugar de los valores. En este 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)) 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());
    }
}
Question

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

Por ejemplo, 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 proporciona el siguiente error en tiempo de compilación:

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

Falla en la palabra clave Suit , la segunda.




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



Agregue el método public static IEnumerable<T> GetValues<T>() a su 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
     }
 }



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

El autor usa un doble for-loop para iterar a través de un par de enumeradores (para crear una baraja completa de cartas):

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 carta con un Suit y Value definidos:

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

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



Yo uso ToString () y luego dividir y analizar la matriz spit en flags.

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



¿Por qué nadie usa Cast<T> ?

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

Ahí tienes IEnumerable<Suit> .




¿Qué diablos voy a lanzar mis dos peniques, simplemente combinando 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 Enum value)
    {
        return (T[])Enum.GetValues(typeof (T));
    }
}

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




enum tipos enum se denominan "tipos de enumeración" no porque sean contenedores que "enumeran" valores (que no son), sino porque se definen al enumerar 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 enum tienen un tipo entero "subyacente", lo que significa que cada valor enum corresponde a un valor entero (esto es típicamente implícito, pero se puede especificar manualmente). de modo que puedas meter cualquier número entero de ese tipo en la variable enum, incluso si no es un valor "nombrado").

El método System.Enum.GetNames se puede usar para recuperar una matriz de cadenas que son los nombres de los valores enum, como su nombre lo sugiere.

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




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



No opino que esto sea mejor, o incluso bueno, solo que establezca otra solución.

Si los valores enum 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 enum 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 estrictamente enumerativo, solo bucle. El segundo método es mucho más rápido que cualquier otro enfoque, aunque ...




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

public List<Enum> GetValues(Enum enumeration)
{
   List<Enum> enumerations = new List<Enum>();
   foreach (FieldInfo fieldInfo in enumeration.GetType().GetFields(
         BindingFlags.Static | BindingFlags.Public))
   {
      enumerations.Add((Enum)fieldInfo.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 guarden en caché.




Una forma simple y genérica de convertir una enumeración en algo que puede 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>();



Solo para agregar mi solución, que funciona en un marco compacto (3.5) y admite el control 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 alegraría ver una solución.

Una llamada se vería así:

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





Related