2011-02-11 10 views
10

Digamos que tengo esta enumeración:¿Cómo conseguir representación en cadena de valor de enumeración compleja

[Flags] 
public enum SomeType 
{  
    Val1 = 0, 
    Val2 = 1, 
    Val3 = 2, 
    Val4 = 4, 
    Val5 = 8, 
    Val6 = 16, 
    All = Val1 | Val2 | Val3 | Val4 | Val5 | Val6 
} 

y algunas variables:

SomeType easyType = SomeType.Val1 | SomeType.Val2; 
SomeType complexType = SomeType.All; 

si quiero colocar a través de los valores de la primera enumeración que pueda simplemente hacer:

foreach(string s in easyType.ToString().Split(',')) 
{ ... } 

Sin embargo, cuando trato de aplicar el mismo enfoque a la 'tipoCompuesto' llego valor 'Todos', que es, por supuesto, válido porque también es uno de los posibles valores de la enumeración. Pero, ¿hay una buena manera de ver realmente de qué valores es el SomeType.All creado? Sé que podría hacer un bucle manual de a través de todos los valores como la que:

if(complexType.HasFlag(ManualType.Val1) && ... 
+0

Creo que el problema es que no se debe poner 'all' dentro de esta enumeración. Como lo marca '[Flags]', no es una buena idea ponerle ninguna combinación. –

+0

Luego, yo (y otros) siempre tendré que recordar usar una combinación adecuada de enumeraciones cuando use SomeType para algo. – IamDeveloper

+0

¿Puedes publicar la enumeración original en lugar de 'SomeType' inútil? –

Respuesta

4
var result = string.Join(",", 
       Enum.GetValues(typeof(SomeType)) 
        .Cast<SomeType>() 
        .Where(v => complexType.HasFlag(v))); 

Se puede escribir una extensión método para evitar repetirse.

+1

¿No incluirá esto también ", All" al final? ¿Necesita eso un caso especial para ignorarlo? – Justin

+0

@Justin: Sí, lo hará. ¿Pero que podemos hacer? ¿Verifica si es "Todo"? ¿Qué pasa si su nombre es "AllOptions"? Entonces no podemos tratar con este "caso especial". –

+0

La única opción que se me ocurre es mantener una ejecución en modo bit a la O de todos los valores previos vistos, y luego ignorar un valor si no contiene ningún bit nuevo. Sin embargo, dependería del orden. – Justin

0

Tal vez usted necesita para enumerar los valores de enumeración y probar cada uno:

foreach (SomeType item in Enum.GetValues (typeof (SomeType)) 
{ 
    if ((complexType & item) == item) 
    { 
    //... 
    } 
} 
+0

Pero luego probaré también para Todos. Está bien en mi situación, pero ¿y si también hubiera definido SomeType.JustThree = Val1 | Val2 | Val3. Es redundante al menos. – IamDeveloper

0

Aquí es una forma posible de hacerlo, sobre la base de la respuesta de Danny Chen:

public IEnumerable<T> GetFlags<T>(Predicate<int> hasFlag) 
{ 
    return GetEnumFlags<T>().Where(f => hasFlag(f)).Cast<T>(); 
} 

private IEnumerable<int> GetEnumFlags<T>() 
{ 
    return Enum.GetValues(typeof(T)).Cast<int>().Where(IsPowerOfTwoOrZero); 
} 

private bool IsPowerOfTwoOrZero(int v) 
{ 
    return ((v & (v-1)) == 0); 
} 

Uso:

void Main() 
{ 
    SomeType easyType = SomeType.Val1 | SomeType.Val2; 
    SomeType complexType = SomeType.All; 

    GetFlags<SomeType>(v => easyType.HasFlag((SomeType)v)); 
    GetFlags<SomeType>(v => complexType.HasFlag((SomeType)v)); 
} 

Nota esto funcionará para enumeraciones basado en tipos moldeables a int. Puede crear métodos similares para long etc.

0

Si está utilizando una enumeración para representar datos que tienen un nivel de complejidad más profundo (grupos arbitrarios de elementos, "oscuridad" de color, etc.) y que tienen dificultades debido a eso , Sugeriría que una enumeración es la construcción de programación incorrecta que se utilizará.

Usar una enumeración para estas tareas siempre será propenso a errores: si agrego un nuevo color a su enumeración, tengo que recordar agregarlo también a "Brillante" u "Oscuro". Eso hace que su código sea tan propenso a errores para los desarrolladores como el problema original. Lo que podría hacer, sin embargo, es definir un class o struct para el color que tiene una propiedad que indica si es brillante o no. Entonces tendrá una funcionalidad clara y comprensible, implementada de una manera que no proporcione resultados espurios como cuando está tratando de utilizar mal una función de lenguaje más simple.

que, por ejemplo, es la razón por Color is a struct ...

Cuestiones relacionadas