¿Cómo enumero una enumeración?

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

Por ejemplo, el siguiente código no se comstack:

 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 comstackción:

‘Traje’ es un ‘tipo’ pero se usa como una ‘variable’

Falla en la palabra clave Suit , la segunda.

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

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

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

 public static class EnumExtensions { ///  /// Gets all items for an enum value. ///  ///  /// The value. ///  public static IEnumerable GetAllItems(this Enum value) { foreach (object item in Enum.GetValues(typeof(T))) { yield return (T)item; } } ///  /// Gets all items for an enum type. ///  ///  /// The value. ///  public static IEnumerable GetAllItems() where T : struct { foreach (object item in Enum.GetValues(typeof(T))) { yield return (T)item; } } ///  /// Gets all combined items from an enum value. ///  ///  /// The value. ///  ///  /// Displays ValueA and ValueB. ///  /// EnumExample dummy = EnumExample.Combi; /// foreach (var item in dummy.GetAllSelectedItems()) /// { /// Console.WriteLine(item); /// } ///  ///  public static IEnumerable GetAllSelectedItems(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; } } } ///  /// Determines whether the enum value contains a specific value. ///  /// The value. /// The request. ///  /// true if value contains the specified value; otherwise, false. ///  ///  ///  /// EnumExample dummy = EnumExample.Combi; /// if (dummy.Contains(EnumExample.ValueA)) /// { /// Console.WriteLine("dummy contains EnumExample.ValueA"); /// } ///  ///  public static bool Contains(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 FlagsAttribute

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

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 GetValues(Enum enumeration) { List enumerations = new List(); 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 reflexión , debe tomar medidas para garantizar que se ejecute solo una vez y que los resultados se guarden en caché.

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 de tiempo de comstackción, no una excepción de tiempo de ejecución, si Suit no es una enum .

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

EnumLoop tiene esta definición completamente genérica:

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

¿Por qué nadie usa Cast ?

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

Ahí tienes IEnumerable .

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

Publicación original del blog por Einar Ingebrigtsen :

 public class EnumHelper { public static T[] GetValues() { Type enumType = typeof(T); if (!enumType.IsEnum) { throw new ArgumentException("Type '" + enumType.Name + "' is not an enum"); } List values = new List(); 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 values = new List(); 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 el control de tipos en tiempo de comstackción :

 public static List GetEnumValues() where T : new() { T valueType = new T(); return typeof(T).GetFields() .Select(fieldInfo => (T)fieldInfo.GetValue(valueType)) .Distinct() .ToList(); } public static List GetEnumNames() { 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 result = Utils.GetEnumValues(); 

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

Escuché rumores vagos de que esto es terriblemente lento. ¿Nadie sabe? – Orion Edwards 15 de octubre de 2008 a la 1:31 7

Creo que almacenar en caché la matriz lo aceleraría considerablemente. Parece que estás obteniendo una nueva matriz (a través de la reflexión) todo el tiempo. 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, ¿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é se introdujo GetEnumValues en la instancia de tipo, no es muy fácil de leer para mí.


Tener una clase de ayuda como Enum es lo más legible y memorable para mí:

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

Ahora llama:

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

También se puede utilizar el tipo de almacenamiento en caché si el rendimiento importa, pero no espero que esto sea un problema en absoluto

 public static class Enum where T : struct, IComparable, IFormattable, IConvertible { //lazily loaded static T[] values; static string[] names; public static IEnumerable GetValues() { return values ?? (values = (T[])Enum.GetValues(typeof(T))); } public static IEnumerable GetNames() { return names ?? (names = Enum.GetNames(typeof(T))); } } 

¿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 { ///  /// Gets all items for an enum value. ///  ///  /// The value. ///  public static IEnumerable GetAllItems(this Enum value) { return (T[])Enum.GetValues(typeof (T)); } } 

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

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 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 formas 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 en una matriz de object , y el segundo le dará valores en forma de matriz de String .

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

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

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() { 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 ...

Si necesita velocidad y verificación de tipos durante la comstackción y el tiempo de ejecución, este método de ayuda es mejor que usar LINQ para convertir cada elemento:

 public static T[] GetEnumValues() 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(); 

Por supuesto, puede devolver IEnumerable , pero eso no le compra nada aquí.

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() }; 
 foreach (Suit suit in Enum.GetValues(typeof(Suit))) { } 

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

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

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

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

Una forma simple y genérica de convertir una enumeración en algo que puede interactuar:

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

Y entonces:

 var enums = EnumHelper.ToList(); 

¿Qué pasa si sabes que el tipo será una enum , pero no sabes cuál es el tipo exacto en tiempo de comstackción?

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

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

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

Agregue el método public static IEnumerable GetValues() a su clase, como

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

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(); foreach (var foo in foos) { // Do something } } 

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

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

enum tipos enum se denominan “tipos de enumeración” no porque sean contenedores que “enumeran” valores (que no son), sino porque se definen 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 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 ​​en su lugar. Oops.