2010-09-08 13 views
25

Tengo una enumeración Marcados y la necesidad de recuperar los nombres de todos los valores establecidos en él.forma más eficiente para analizar una enumeración Marcados a una lista

Actualmente estoy aprovechando el método ToString() de la enumeración, que devuelve los elementos separados por comas.

public void SetRoles(Enums.Roles role) 
    { 
     IList<Entities.Role> roleList = role.ToString("G").Split(',') 
      .Select(r => new Entities.Role(r.Trim())) 
      .ToList(); 
    ... 
    } 

Estoy seguro de que debe haber una manera mejor que esta.

+0

Es bueno saber que existe algo así como 'el método ToString() de la enumeración que devuelve los elementos separados por comas'. Me has alegrado el día :). +1. – RBT

Respuesta

22

¡Buena pregunta!

no puedo pensar en nada mejor que:

public void SetRoles(Enums.Roles role) 
{ 
    List<string> result = new List<string>(); 
    foreach(Roles r in Enum.GetValues(typeof(Roles)) 
    { 
    if ((role & r) != 0) result.Add(r.ToString()); 
    } 
} 
+3

Mejor reemplace '(role & r)! = 0' con' (role & r) == r' o 'role.HasFlag (r)' en .net4. Y asegúrese de asignar valores que sean una potencia de 2; de lo contrario, fallará. Ver http://stackoverflow.com/questions/8447/enum-flags-attribute –

+8

Aquí está una versión de línea de la misma: 'Enum.GetValues ​​(typeof (Roles)). Cast () .Where (r => (role & r) == r) .Select (r => r.ToString()) ' – Ondra

+2

Además, en lugar de if ((role & r)! = 0) use role.HasFlag (r) – dlchambers

3

¿Por qué necesita una lista? Todo ya está almacenada en las banderas:

[Flags] 
enum Roles 
{ 
    Read = 0x1, 
    Write = 0x2, 
    Delete = 0x4, 
} 

a continuación, asignar roles:

var roles = Roles.Read | Roles.Write; 

Y siempre que lo necesite para comprobar si una función dada ha sido que no es necesario para buscar en una lista, pero simplemente busque en la enumeración de roles:

if ((roles & Roles.Read) == Roles.Read) 
{ 
    // The user has read permission 
} 
if ((roles & Roles.Write) == Roles.Write) 
{ 
    // The user has write permission 
} 
+2

Así es como la aplicación lo está utilizando. Sin embargo, esto es más una preocupación de persistencia. Prefiero dejar este método sin saber qué valores puede contener la enumeración. –

+3

Si es por persistencia, todo lo que necesita almacenar es un entero único que representa las banderas porque este entero le permite extraer más adelante todos los roles. No es necesario almacenar listas. De lo contrario, '[Banderas]' es algo innecesario si va a mantener listas de roles. También obtendrá algunos bytes de medios de almacenamiento :-) –

+1

Sin embargo, a veces es importante mantener los datos almacenados en un formato algo legible para los humanos. En ese caso, Enum.Parse puede manejar valores enum concatenados muy bien, de forma similar a como ToString() los emite. Entonces 'Enum.Parse (typeof (Roles)," Read, Write ")' dará como resultado la lectura correcta | Escribir valor En realidad, escribiré una respuesta con esta información. –

7

Enum.Parse se encargará de los valores concatenados que salen de ToString bien. Prueba usando la ventana Inmediato:

? System.Enum.Parse(typeof(System.AttributeTargets), "Class, Enum") 
Class | Enum 

(la segunda línea es la salida, que es diferente en el depurador/ventana inmediata de la salida Enum.ToString genérica()).

21

Si realmente sólo quiere las cadenas, no se puede conseguir mucho más simple que:

string[] flags = role.ToString().Split(',');

Esto es más simple que el uso de LINQ y sigue siendo sólo una sola línea de código. O si desea una lista en lugar de una matriz como en la muestra de la pregunta se puede convertir la matriz en una lista:

List<string> flags = new List<string>(role.ToString().Split(','));

En mi caso necesitaba una solución genérica y se acercó con esto:

value.ToString().Split(',').Select(flag => (T)Enum.Parse(typeof(T), flag)).ToList();

+0

La mejor respuesta. ¡Gracias! – Ricsie

Cuestiones relacionadas