c# declare to how Come faccio a enumerare un enum in C #?




13 Answers

Mi sembra che tu voglia davvero stampare i nomi di ogni enumerazione, piuttosto che i valori. In tal caso, Enum.GetNames() sembra essere l'approccio giusto.

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

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

A proposito, incrementare il valore non è un buon modo per enumerare i valori di un enum. Dovresti farlo invece.

Enum.GetValues(typeof(Suit)) .

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

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

Come puoi enumerare un enum in C #?

Ad esempio il seguente codice non viene compilato:

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

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

E dà il seguente errore in fase di compilazione:

'Suit' è un 'tipo' ma è usato come una 'variabile'

Fallisce sulla parola chiave Suit , la seconda.




Alcune versioni del framework .NET non supportano Enum.GetValues . Ecco una buona soluzione alternativa di Ideas 2.0: Enum.GetValues ​​in 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;
}

Come con qualsiasi codice che comporta la reflection , è necessario adottare misure per assicurarsi che venga eseguito una sola volta e che i risultati vengano memorizzati nella cache.




Perché nessuno usa Cast<T> ?

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

IEnumerable<Suit> .




Solo per aggiungere la mia soluzione, che funziona in framework compatto (3.5) e supporta il controllo dei tipi in fase di compilazione :

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

- Se qualcuno sa come eliminare T valueType = new T() , sarei felice di vedere una soluzione.

Una chiamata sarebbe simile a questa:

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



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



Tre modi:

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

Non sono sicuro perché sia ​​stato introdotto GetEnumValues tipo, non è molto leggibile per me.

Avere una classe di supporto come Enum<T> è ciò che è più leggibile e memorabile per me:

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

Adesso chiami:

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

Si può anche utilizzare una sorta di memorizzazione nella cache se le prestazioni sono importanti, ma non mi aspetto che questo sia un problema

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



Uso ToString () quindi divido e analizzo l'array spit in flag.

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



Non ritengo che questo sia meglio, o addirittura buono, semplicemente affermando l'ennesima soluzione.

Se i valori enum variano strettamente da 0 a n - 1, un'alternativa generica:

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

Se i valori enum sono contigui e puoi fornire il primo e l'ultimo elemento dell'enumerazione, allora:

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

ma questo non è strettamente enumerativo, solo looping. Il secondo metodo è molto più veloce di qualsiasi altro approccio però ...




ecco un esempio funzionante di creazione di opzioni di selezione per 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()
      };



Questa domanda appare nel capitolo 10 di " C # Step by Step 2013 "

L'autore usa un doppio ciclo per iterare attraverso una coppia di Enumeratori (per creare un mazzo completo di carte):

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

In questo caso, Suit e Value sono entrambi enumerazioni:

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

e PlayingCard è un oggetto di carta con un Suit e un Value definiti:

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

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



Un modo semplice e generico per convertire un enum in qualcosa che puoi interagire:

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

E poi:

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



Aggiungi metodo public static IEnumerable<T> GetValues<T>() alla tua classe, come

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

chiama e passa il tuo enum, ora puoi scorrere attraverso il foreach

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



enum tipi di enum sono chiamati "tipi di enumerazione" non perché sono contenitori che "enumerano" valori (che non sono), ma perché sono definiti enumerando i possibili valori per una variabile di quel tipo.

(In realtà, questo è un po 'più complicato di quello - i tipi di enum sono considerati con un tipo intero "sottostante", il che significa che ogni valore enum corrisponde a un valore intero (questo è tipicamente implicito, ma può essere specificato manualmente). in un modo tale da poter inserire qualsiasi numero intero di quel tipo nella variabile enum, anche se non è un valore "named".)

Il metodo System.Enum.GetNames può essere utilizzato per recuperare un array di stringhe che sono i nomi dei valori enum, come suggerisce il nome.

EDIT: avrebbe dovuto suggerire invece il metodo System.Enum.GetValues . Ops.




Related