2009-07-22 18 views
451

¿Hay alguna forma de convertir un enum en una lista que contenga todas las opciones de enum?¿Cómo convierto una enumeración en una lista en C#?

+1

Preguntas muy relacionadas: [¿Cómo enumerar una enumeración?] (Http://stackoverflow.com/questions/105372/), [¿Se puede pasar por todos los valores de Enum? (duplicado)] (http://stackoverflow.com/questions/972307/). –

+0

[Las entradas y salidas de C# enumeraciones] (http://www.codeducky.org/ins-outs-c-enums/) describe cómo hacer esto (la misma respuesta que a continuación), así como un montón de otras enumeraciones comunes operaciones. – ChaseMedallion

+0

Creo que si estás buscando hacer esto, quizás quieras pensar si realmente deberías estar usando una enumeración o si debes cambiar a un objeto que represente w/e tu enum. –

Respuesta

771

Esto devolverá IEnumerable<SomeEnum> de todos los valores de un Enum.

Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>(); 

Si quieren que para ser un List<SomeEnum>, sólo tiene que añadir .ToList() después .Cast<SomeEnum>().

Para usar la función de Cast en una matriz, necesita tener el System.Linq en la sección de uso.

+0

nice ... its is working Array arr = (Array) Enum.GetValues ​​(typeof (SomeEnum)). Cast (); ¿Es correcto trabajar esta línea de código? –

+2

En realidad el resultado de moldeada() es un IEnumerable así que si quieres una matriz que tendría que cambiar su línea para:. array 'var = Enum.GetValues ​​(typeof (SomeEnum)) Reparto () .ToArray (); ' –

+58

eso es superfluo, y significará copia adicional. 'Enum.GetValues' ya devuelve una matriz, por lo que solo tiene que hacer' var values ​​= (SomeEnum []) Enum.GetValues ​​(typeof (SomeEnum)) ' – thecoop

2
public class NameValue 
{ 
    public string Name { get; set; } 
    public object Value { get; set; } 
} 

public class NameValue 
{ 
    public string Name { get; set; } 
    public object Value { get; set; } 
} 

public static List<NameValue> EnumToList<T>() 
{ 
    var array = (T[])(Enum.GetValues(typeof(T)).Cast<T>()); 
    var array2 = Enum.GetNames(typeof(T)).ToArray<string>(); 
    List<NameValue> lst = null; 
    for (int i = 0; i < array.Length; i++) 
    { 
     if (lst == null) 
      lst = new List<NameValue>(); 
     string name = array2[i]; 
     T value = array[i]; 
     lst.Add(new NameValue { Name = name, Value = value }); 
    } 
    return lst; 
} 

Convertir Enum A más información disponible here. forma

+0

Fundir en 'T []' el valor de retorno de 'Cast ' es innecesariamente confuso. Ver mi respuesta reciente. –

71

Mucho más fácil:

Enum.GetValues(typeof(SomeEnum)) 
    .Cast<SomeEnum>() 
    .Select(v => v.ToString()) 
    .ToList(); 
+12

¿Por qué 'ToList()' entre Cast y Select? ¿Y cómo es eso mucho más fácil que la respuesta aceptada? Es idéntico a él, excepto que convierte a 'cadena' al final. – CodesInChaos

+1

Simplemente compare la cantidad de código para esta operación tan simple. Además, esto es más una solución .NETy para este problema. De acuerdo en ToList(). – Gili

+3

Creo que puede usar Enum.GetNames (typeof (SomeEnum)). ToList() ahora – JasonWilczak

19
List <SomeEnum> theList = Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>().ToList(); 
+1

Esto asigna dos colecciones para contener los valores y descarta una de esas colecciones. Ver mi respuesta reciente. –

4

Aquí para utilidad ... algo de código para obtener los valores en una lista, que convierte la enumeración en forma legible para el texto

public class KeyValuePair 
    { 
    public string Key { get; set; } 

    public string Name { get; set; } 

    public int Value { get; set; } 

    public static List<KeyValuePair> ListFrom<T>() 
    { 
     var array = (T[])(Enum.GetValues(typeof(T)).Cast<T>()); 
     return array 
     .Select(a => new KeyValuePair 
      { 
      Key = a.ToString(), 
      Name = a.ToString().SplitCapitalizedWords(), 
      Value = Convert.ToInt32(a) 
      }) 
      .OrderBy(kvp => kvp.Name) 
     .ToList(); 
    } 
    } 

.. y el método de extensión System.String compatible:

/// <summary> 
/// Split a string on each occurrence of a capital (assumed to be a word) 
/// e.g. MyBigToe returns "My Big Toe" 
/// </summary> 
public static string SplitCapitalizedWords(this string source) 
{ 
    if (String.IsNullOrEmpty(source)) return String.Empty; 
    var newText = new StringBuilder(source.Length * 2); 
    newText.Append(source[0]); 
    for (int i = 1; i < source.Length; i++) 
    { 
    if (char.IsUpper(source[i])) 
     newText.Append(' '); 
    newText.Append(source[i]); 
    } 
    return newText.ToString(); 
} 
+0

Cuando dice '(T []) (Enum.GetValues ​​(typeof (T)).Emitir ()) ', mirando detenidamente los paréntesis, vemos que en realidad arroja el valor devuelto de' Cast 'a' T [] '. Eso es bastante confuso (y quizás sorprendente, incluso funcionará). Omita la llamada 'Cast '. Ver mi nueva respuesta para más detalles. –

5

Siempre he usado para obtener una lista de valores enum así:

Array list = Enum.GetValues(typeof (SomeEnum)); 
+2

Esto le dará una matriz, no lista <>. – Shenaniganz

0

se puede utilizar el siguiente método genérico:

public static List<T> GetItemsList<T>(this int enums) where T : struct, IConvertible 
    { 
     if (!typeof (T).IsEnum) 
     { 
      throw new Exception("Type given must be an Enum"); 
     } 

     return (from int item in Enum.GetValues(typeof (T)) 
       where (enums & item) == item 
       select (T) Enum.Parse(typeof (T), item.ToString(new CultureInfo("en")))).ToList(); 
    } 
+0

Primero obtienes los valores, luego echas cada uno a 'int', luego llamas' ToString' con una cultura extraña en ese 'int', luego vuelve a analizar la cadena para escribir' T'? Downvoted. –

+0

Sí, fundir todos los valores en int para comprobar, does enums contiene item, cuando se lanza a string para analizar enum back. Este método es más útil con BitMask. CultureInfo no requerido. – Vitall

1
/// <summary> 
/// Method return a read-only collection of the names of the constants in specified enum 
/// </summary> 
/// <returns></returns> 
public static ReadOnlyCollection<string> GetNames() 
{ 
    return Enum.GetNames(typeof(T)).Cast<string>().ToList().AsReadOnly(); 
} 

donde T es un tipo de Enumeración; Añadir este :

using System.Collections.ObjectModel; 
0

Si desea Enum int como la clave y el nombre como valor, bueno si almacenar el número a la base de datos y es a partir de enumeración!

void Main() 
{ 
    ICollection<EnumValueDto> list = EnumValueDto.ConvertEnumToList<SearchDataType>(); 

    foreach (var element in list) 
    { 
     Console.WriteLine(string.Format("Key: {0}; Value: {1}", element.Key, element.Value)); 
    } 

    /* OUTPUT: 
     Key: 1; Value: Boolean 
     Key: 2; Value: DateTime 
     Key: 3; Value: Numeric   
    */ 
} 

public class EnumValueDto 
{ 
    public int Key { get; set; } 

    public string Value { get; set; } 

    public static ICollection<EnumValueDto> ConvertEnumToList<T>() where T : struct, IConvertible 
    { 
     if (!typeof(T).IsEnum) 
     { 
      throw new Exception("Type given T must be an Enum"); 
     } 

     var result = Enum.GetValues(typeof(T)) 
         .Cast<T>() 
         .Select(x => new EnumValueDto { Key = Convert.ToInt32(x), 
             Value = x.ToString(new CultureInfo("en")) }) 
         .ToList() 
         .AsReadOnly(); 

     return result; 
    } 
} 

public enum SearchDataType 
{ 
    Boolean = 1, 
    DateTime, 
    Numeric 
} 
9

respuesta muy simple

Aquí es una propiedad que utilizo en una de mis aplicaciones

public List<string> OperationModes 
{ 
    get 
    { 
     return Enum.GetNames(typeof(SomeENUM)).ToList(); 
    } 
} 
19

Esta es la forma que amo, utilizando LINQ:

public class EnumModel 
{ 
    public int Value { get; set; } 
    public string Name { get; set; } 
} 

public enum MyEnum 
{ 
    Name1=1, 
    Name2=2, 
    Name3=3 
} 

public class Test 
{ 
    List<EnumModel> enums = ((MyEnum[])Enum.GetValues(typeof(MyEnum))).Select(c => new EnumModel() { Value = (int)c, Name = c.ToString() }).ToList(); 
} 

Esperanza ayuda

+11

'((IEnumerable ) Enum.GetValues' debería ser' ((IEnumerable ) Enum.GetValues' –

+0

Gracias @StevenAnderson, He arreglado el anwser. – Booster2ooo

+0

Eso es un gran ejemplo! Me gusta cómo mostrar el modelo, y el uso de enumeración . Estaba un poco atrapado en qué hacer hasta ver tu respuesta. ¡Gracias! – Rich

1
private List<SimpleLogType> GetLogType() 
{ 
    List<SimpleLogType> logList = new List<SimpleLogType>(); 
    SimpleLogType internalLogType; 
    foreach (var logtype in Enum.GetValues(typeof(Log))) 
    { 
    internalLogType = new SimpleLogType(); 
    internalLogType.Id = (int) (Log) Enum.Parse(typeof (Log), logtype.ToString(), true); 
    internalLogType.Name = (Log)Enum.Parse(typeof(Log), logtype.ToString(), true); 
    logList.Add(internalLogType); 
    } 
    return logList; 
} 

en el código superior, el registro es un Enum y SimpleLogType es una estructura para los registros.

public enum Log 
{ 
    None = 0, 
    Info = 1, 
    Warning = 8, 
    Error = 3 
} 
+0

Su variable 'foreach' tiene' 'object' del tipo de tiempo de compilación' (escrito como' var'), pero realmente es un valor 'Log' (tipo de tiempo de ejecución). No es necesario llamar 'ToString' y luego' Enum.Parse'. Comience su 'foreach' con esto en su lugar:' foreach (var logtype in (Log []) Enum.GetValues ​​(typeof (Log))) {...} ' –

60

La respuesta corta es, usar:

(SomeEnum[])Enum.GetValues(typeof(SomeEnum)) 

Si necesita que para una variable local, es var allSomeEnumValues = (SomeEnum[])Enum.GetValues(typeof(SomeEnum));.

¿Por qué es la sintaxis así ?!

El método staticGetValues se introdujo en los antiguos .NET 1.0 días. Devuelve una matriz unidimensional del tipo de tiempo de ejecución SomeEnum[]. Pero dado que es un método no genérico (los genéricos no se introdujeron hasta .NET 2.0), no puede declarar su tipo de devolución (tipo de devolución en tiempo de compilación) como tal.

matrices .NET tienen una especie de covarianza, sino porque SomeEnum habrá un tipo valor, y por tipo de matriz de covarianza no funciona con tipos de valor, ni siquiera podían declarar el tipo de retorno como una object[] o Enum[]. (Esto es diferente de por ejemplo this overload of GetCustomAttributes from .NET 1.0 que tiene tiempo de compilación de retorno tipo object[] pero en realidad devuelve una matriz de tipo SomeAttribute[] donde SomeAttribute es necesariamente un tipo de referencia.)

Debido a esto, el método .NET 1.0 tuvo que declarar su regreso escriba como System.Array. Pero te garantizo que es un SomeEnum[].

Cada vez que llame al GetValues nuevamente con el mismo tipo de enumeración, tendrá que asignar una nueva matriz y copiar los valores en la nueva matriz. Esto se debe a que el "consumidor" del método debe escribir las matrices (modificadas), por lo que debe crear una nueva matriz para asegurarse de que los valores no se hayan modificado. .NET 1.0 no tenía buenas colecciones de solo lectura.

Si necesita la lista de todos los valores de muchos lugares diferentes, considere llamar GetValues sólo una vez y almacenar en caché el resultado de sólo lectura envoltura, por ejemplo, así:

public static readonly ReadOnlyCollection<SomeEnum> AllSomeEnumValues 
    = Array.AsReadOnly((SomeEnum[])Enum.GetValues(typeof(SomeEnum))); 

continuación, puede utilizar AllSomeEnumValues muchas veces , y la misma colección se puede reutilizar de forma segura.

¿Por qué es malo usar .Cast<SomeEnum>()?

Muchas otras respuestas usan .Cast<SomeEnum>(). El problema con esto es que utiliza la implementación no genérica IEnumerable de la clase Array. Este debe incluir encajonar cada uno de los valores en un cuadro System.Object y, a continuación, utilizar el método Cast<> para volver a poner en la caja todos esos valores. Afortunadamente, el método .Cast<> parece verificar el tipo de tiempo de ejecución de su parámetro IEnumerable (el parámetro this) antes de que comience a recorrer la colección, por lo que no es tan malo después de todo. Resulta que .Cast<> deja pasar la misma instancia de matriz.

Si sigue por .ToArray() o .ToList(), como en:

Enum.GetValues(typeof(SomeEnum)).Cast<SomeEnum>().ToList() // DON'T do this 

tiene otro problema: Se crea una nueva colección (matriz) cuando se llama GetValues y luego crear todavía una nueva colección (List<>) con la llamada .ToList(). Entonces esa es una asignación (extra) redundante de una colección completa para contener los valores.

+1

Terminé aquí buscando una manera de obtener una lista < > desde mi enumeración, no una matriz. Si solo desea recorrer su enumeración, esto es genial, pero el .Cast () .ToList() le proporciona una colección IEnumerable, que es valiosa en algunas situaciones. – DaveD

+2

@DaveD La expresión '(SomeEnum []) Enum.GetValues ​​(typeof (SomeEnum))' también es 'IEnumerable' y' IEnumerable ', y es' IList' y 'IList ' también. Pero si necesita agregar o eliminar entradas más adelante, de modo que la longitud de la lista cambie, * puede * copiar a 'List ', pero esa no es la necesidad más habitual. –

+1

Siempre me he preguntado por qué no solo agregan un 'Enum.GetValue ()'. –

3
Language[] result = (Language[])Enum.GetValues(typeof(Language)) 
Cuestiones relacionadas