¿Cómo se puede enumerar un 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 da el siguiente error en tiempo de compilación:
'Traje' es un 'tipo' pero se usa como una 'variable'
Falla en la Suit
palabra clave, la segunda.
Respuestas:
Nota : La conversión a
(Suit[])
no es estrictamente necesaria, pero hace que el código sea 0.5 ns más rápido .fuente
enum.GetValues
. Tienes que usar la reflexión en este caso.enum E {A = 0, B = 0}
.Enum.GetValues
da como resultado la devolución de dos valores, aunque son los mismos.E.A == E.B
es cierto, entonces no hay distinción. Si desea nombres individuales, entonces debe buscarEnum.GetNames
.Distinct
extensión de Linq (desde .NET 3.5), entoncesforeach (var suit in ((Suit[])Enum.GetValues(typeof(Suit))).Distinct()) { }
.var
para el tipo. El compilador convertirá la variable en unObject
lugar de la enumeración. Listar el tipo de enumeración explícitamente.Me parece que realmente quieres imprimir los nombres de cada enumeración, en lugar de los valores. En cuyo caso
Enum.GetNames()
parece ser el enfoque correcto.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 en su
Enum.GetValues(typeof(Suit))
lugar.fuente
Enum.GetValues(typeof(Suits)).OfType<Suits>().ToArray()
. En ese caso, puedo iterar una matriz deSuits
elementos de enumeración, no cadenas.Suits suit in Enum.GetValues(typeof(Suits))
?Hice algunas extensiones para facilitar el uso de la enumeración. Quizás alguien pueda usarlo ...
La enumeración en sí debe estar decorada con el atributo FlagsAttribute :
fuente
Algunas versiones de .NET Framework no son compatibles
Enum.GetValues
. Aquí hay una buena solución de Ideas 2.0: Enum.GetValues en Compact Framework :Al igual que con cualquier código que implique reflexión , debe tomar medidas para asegurarse de que se ejecute solo una vez y que los resultados se almacenen en caché.
fuente
return type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)).Cast<Enum>();
Uso
Cast<T>
:Hay que ir,
IEnumerable<Suit>
.fuente
from
cláusula y elforeach
declarador de encabezado.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 obtiene un error en tiempo de compilación, no una excepción de tiempo de ejecución siSuit
no es unenum
.EnumLoop
tiene esta definición completamente genérica:fuente
EnumLoop
algún tipo que no sea una enumeración, se compilará bien, pero arrojará una excepción en tiempo de ejecución.No entrarás
Enum.GetValues()
en Silverlight .Publicación de blog original de Einar Ingebrigtsen :
fuente
where T: Enum
Mi solución funciona en .NET Compact Framework (3.5) y admite la verificación de tipos en tiempo de compilación :
T valueType = new T()
, me encantaría ver una solución.Una llamada se vería así:
fuente
T valueType = default(T)
?new()
T
. Además, no necesitanew T()
nada, puede seleccionar solo los campos estáticos y hacer.GetValue(null)
. Ver la respuesta de Aubrey.where T: Enum
Creo que puedes usar
fuente
fuente
Creo que el almacenamiento en caché de la matriz lo aceleraría considerablemente. Parece que está obteniendo una nueva matriz (a través de la reflexión) cada vez. Más bien:
Eso es al menos un poco más rápido, ¿ja?
fuente
Tres maneras:
Enum.GetValues(type)
// Desde .NET 1.1, no en Silverlight o .NET Compact Frameworktype.GetEnumValues()
// Solo en .NET 4 y superiortype.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null))
// Funciona en todas partesNo estoy seguro de por qué
GetEnumValues
se introdujo en instancias de tipo. No es muy legible para mí.Tener una clase auxiliar
Enum<T>
es lo que es más legible y memorable para mí:Ahora llamas:
También se puede usar algún tipo de almacenamiento en caché si el rendimiento es importante, pero no espero que esto sea un problema en absoluto.
fuente
Simplemente combinando las respuestas principales, creé una extensión muy simple:
Es limpio, simple y, según el comentario de @ Jeppe-Stig-Nielsen, rápido.
fuente
where T: Enum
Hay dos formas de iterar un
Enum
:El primero le dará valores en forma en una matriz de **
object
** s, y el segundo le dará valores en forma de una matriz de **String
** s.Úselo en un
foreach
bucle como a continuación:fuente
Uso ToString () y luego divido y analizo la matriz de spit en banderas.
fuente
No creo que esto sea mejor, ni siquiera bueno. Solo estoy diciendo otra solución más.
Si los valores de enumeración varían estrictamente de 0 a n - 1, una alternativa genérica es:
Si los valores de enumeración son contiguos y puede proporcionar el primer y último elemento de la enumeración, entonces:
Pero eso no es estrictamente enumerar, solo hacer un bucle. Sin embargo, el segundo método es mucho más rápido que cualquier otro enfoque ...
fuente
Si necesita comprobación de velocidad y tipo en tiempo de compilación y ejecución, este método auxiliar es mejor que usar LINQ para convertir cada elemento:
Y puedes usarlo como a continuación:
Por supuesto que puedes regresar
IEnumerable<T>
, pero eso no te compra nada aquí.fuente
where T: Enum
Aquí hay un ejemplo de trabajo para crear opciones de selección para un DDL :
fuente
(La respuesta aceptada actual tiene un reparto que no creo que sea necesario (aunque puedo estar equivocado)).
fuente
Esta pregunta aparece en el Capítulo 10 de " C # paso a paso 2013 "
El autor utiliza un doble for-loop para iterar a través de un par de enumeradores (para crear una baraja completa de cartas):
En este caso,
Suit
yValue
son ambas enumeraciones:y
PlayingCard
es un objeto de tarjeta con un definidoSuit
yValue
:fuente
Sé que es un poco desordenado, pero si eres fanático de las frases sencillas, aquí hay una:
fuente
¿Qué
enum
sucede si sabe que el tipo será un , pero no sabe cuál es el tipo exacto en tiempo de compilación?El método
getListOfEnum
usa la reflexión para tomar cualquier tipo de enumeración y devuelve unoIEnumerable
de todos los valores de enumeración.Uso:
fuente
Una forma simple y genérica de convertir una enumeración en algo con lo que pueda interactuar:
Y entonces:
fuente
Dictionary
no es una buena idea: si tienes un meEnum
gustaenum E { A = 0, B = 0 }
, el valor 0 se agrega 2 veces generando unArgumentException
(¡no puedes agregar lo mismoKey
enDictionary
2 o más veces!).Dictionary<,>
de un método llamadoToList
? Además, ¿por qué no volverDictionary<T, string>
?Agregue un método
public static IEnumerable<T> GetValues<T>()
a su clase, como:Llama y pasa tu enumeración. Ahora puedes recorrerlo usando
foreach
:fuente
enum
los tipos se denominan "tipos de enumeración" no porque sean contenedores que "enumeren" valores (que no lo 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 de enumeración tienen un tipo entero "subyacente", lo que significa que cada valor de enumeración corresponde a un valor entero (esto generalmente es implícito, pero puede especificarse manualmente). C # fue diseñado en cierto modo para que puedas rellenar cualquier número entero 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 su nombre.
EDITAR: Debería haber sugerido el método System.Enum.GetValues en su lugar. Ups
fuente
GetNames
método devuelve, de hecho, una matriz de cadenas, pero el OP requiere un enumerador a través de los valores.Lo intenté de muchas maneras y obtuve el resultado de este código:
Para obtener una lista de int de una enumeración, use lo siguiente. ¡Funciona!
fuente
También puede vincularse a los miembros estáticos públicos de la enumeración directamente mediante el uso de la reflexión:
fuente
Si usted tiene:
Esta:
Saldrá:
fuente
Manera genérica de LINQ :
Uso:
fuente