Si tengo una variable que contiene una enumeración de banderas, ¿puedo iterar sobre los valores de bits en esa variable específica? ¿O tengo que usar Enum.GetValues para iterar sobre toda la enumeración y verificar cuáles están configurados?
c#
enums
enum-flags
Olivier Rogier
fuente
fuente
Respuestas:
fuente
HasFlag
está disponible desde .NET 4 en adelante.Enum.GetValues(input.GetType()).Cast<Enum>().Where(input.HasFlag);
Entonces solo:myEnum.GetFLags()
:)static IEnumerable<Enum> GetFlags(this Enum input)
Aquí hay una solución de Linq al problema.
fuente
.Where(v => !Equals((int)(object)v, 0) && e.HasFlag(v));
si tiene un valor cero para representarNone
No hay ningún método integrado para obtener cada componente hasta donde yo sé. Pero aquí hay una forma de obtenerlos:
Adapte lo que
Enum
hace internamente para generar la cadena para devolver las banderas. Puede mirar el código en reflector y debería ser más o menos equivalente. Funciona bien para casos de uso general donde hay valores que contienen múltiples bits.El método de extensión
GetIndividualFlags()
obtiene todas las banderas individuales para un tipo. Por lo tanto, los valores que contienen múltiples bits quedan fuera.fuente
Bar
,Baz
y enBoo
lugar de soloBoo
.Boo
(el valor devuelto usandoToString()
). Lo modifiqué para permitir solo banderas individuales. Entonces, en mi ejemplo, puedes obtenerBar
y enBaz
lugar deBoo
.Volviendo a esto unos años más tarde, con un poco más de experiencia, mi respuesta final solo para valores de un solo bit, pasar del bit más bajo al más alto, es una ligera variante de la rutina interna de Jeff Mercado:
Parece funcionar, y a pesar de mis objeciones de hace algunos años, uso HasFlag aquí, ya que es mucho más legible que usar comparaciones bit a bit y la diferencia de velocidad es insignificante para cualquier cosa que haga. (Es completamente posible que hayan mejorado la velocidad de HasFlags desde entonces de todos modos, por lo que sé ... no lo he probado).
fuente
yield return bits;
?Saliendo del método de @ Greg, pero agregando una nueva característica de C # 7.3, la
Enum
restricción:La nueva restricción permite que este sea un método de extensión, sin tener que transmitir
(int)(object)e
, y puedo usar elHasFlag
método y transmitir directamenteT
desdevalue
.C # 7.3 también agregó restricciones para retrasos y
unmanaged
.fuente
flags
parámetro fuera del tipo genéricoT
, de lo contrario tendría que especificar explícitamente el tipo de enumeración cada vez que lo llame.+1 por la respuesta proporcionada por @ RobinHood70. Descubrí que una versión genérica del método era conveniente para mí.
EDITAR Y +1 para @AustinWBryan por traer C # 7.3 al espacio de solución.
fuente
No necesita iterar todos los valores. simplemente verifique sus banderas específicas de esta manera:
o (como dijo pstrjds en los comentarios) puede verificar su uso como:
fuente
Lo que hice fue cambiar mi enfoque, en lugar de escribir el parámetro de entrada del método como el
enum
tipo, lo escribí como una matriz delenum
tipo (MyEnum[] myEnums
), de esta manera solo itero a través de la matriz con una declaración de interruptor dentro del bucle.fuente
No estaba satisfecho con las respuestas anteriores, aunque fueron el comienzo.
Después de juntar algunas fuentes diferentes aquí:
póster anterior en el
código SO QnA de este hilo Enum Flags Check Post
Great Enum <T> Utility
Creé esto, así que déjame saber lo que piensas.
Parámetros::
bool checkZero
le dice que permita0
como valor de bandera. Por defectoinput = 0
devuelve vacío.bool checkFlags
: le dice que compruebe siEnum
está decorado con el[Flags]
atributo.PD. No tengo tiempo en este momento para descubrir el
checkCombinators = false
alg que lo obligará a ignorar cualquier valor de enumeración que sea una combinación de bits.Esto hace uso de Helper Class Enum <T> que se encuentra aquí y que actualicé para usar
yield return
paraGetValues
:Finalmente, aquí hay un ejemplo de cómo usarlo:
fuente
Sobre la base de la respuesta de Greg anterior, esto también se ocupa del caso en el que tiene un valor 0 en su enumeración, como Ninguno = 0. En cuyo caso, no debe iterar sobre ese valor.
¿Alguien sabría cómo mejorar esto aún más para que pueda manejar el caso en que todas las banderas en la enumeración se configuran de una manera súper inteligente que podría manejar todo el tipo de enumeración subyacente y el caso de All = ~ 0 y All = EnumValue1 | EnumValue2 | EnumValue3 | ...
fuente
Puedes usar un iterador de Enum. A partir del código MSDN:
No está probado, así que si cometí un error, no dudes en llamarme. (obviamente no es reentrante). Debería asignar un valor de antemano o dividirlo en otra función que use enum.dayflag y enum.days. Es posible que pueda ir a algún lugar con el esquema.
fuente
Podría ser también el siguiente código:
Entra solo si el valor de enumeración está contenido en el valor
fuente
Todas las respuestas funcionan bien con indicadores simples, probablemente se meterá en problemas cuando se combinen indicadores.
probablemente necesite agregar un cheque para probar si el valor de enumeración en sí mismo es una combinación. Probablemente necesite algo como lo publicado aquí por Henk van Boeijen para cubrir su requerimiento (debe desplazarse un poco hacia abajo)
fuente
Método de extensión que utiliza la nueva restricción Enum y genéricos para evitar la conversión:
fuente
Puede hacerlo directamente mediante la conversión a int, pero perderá la verificación de tipos. Creo que la mejor manera es usar algo similar a mi propuesta. Mantiene el tipo correcto todo el camino. No se requiere conversión. No es perfecto debido al boxeo que agregará un poco de éxito en el rendimiento.
No es perfecto (boxeo), pero hace el trabajo sin advertencia ...
Uso:
fuente