2011-08-20 12 views
6

El MSDN documentation para el atributo Flag dice que usted debe:enumeraciones bandera sin poder de dos valores

definir constantes de enumeración en potencias de dos, es decir, 1, 2, 4, 8, etc. . Esto significa que los indicadores individuales en las constantes de enumeración combinada no se superponen.

... y, por supuesto, siempre trato de recordar hacer eso. Sin embargo, no hay nada que hacer cumplir y si usted acaba de crear una enumeración el camino 'básico' como ...

[Flags] 
public enum BrokenEnum 
{ 
    None, 
    FirstOption, 
    SecondOption, 
    ThirdOption 
} 

... no se comportará como se espera. Para combatir esto, estoy buscando algún tipo de análisis de código estático (como FxCop) que pueda avisarme cuando haya una enumeración como la anterior en mi código. La advertencia más cercana que pude encontrar fue 'CA1008: Enums should have zero value', que también es útil para diseñar la enumeración de indicadores correctamente, pero no es suficiente.

¿Cuál es la mejor forma de encontrar enumeraciones de banderas incorrectamente diseñadas en mi código? Cuanto más automatizada sea la solución, mejor.

Respuesta

2

Como dice Jacob, puede ser útil tener mezclas de banderas ... pero posiblemente podrías indicar eso de alguna manera para que a tu detección no le importe.

No debería ser demasiado difícil escribir una prueba unitaria que pasa por cada enumeración en una asamblea decorado con [Flags] y comprueba que hay un valor de 0 (posiblemente asegurando que se llama None o Default) y que cualquier otro valor definido (desde Enum.GetValues()) es una potencia de dos. Puede verificarlo usando if ((x & (x - 1)) == 0).

Es posible que tenga algo así como un atributo [Combination] para indicar los valores que están diseñados para ser combinaciones ... incluso podrían indicar los nombres de los indicadores que están destinados a ser combinaciones, para que pueda verificar eso también.

Sé que esto no es tan bueno como una verificación en tiempo de compilación, pero suponiendo que ya está ejecutando pruebas regularmente, es bastante cercano.

+1

supongo que no debería haber estado pensando 'dentro de la caja' de análisis de código estático. Una prueba de unidad como esta debería ser bastante fácil y darme casi el mismo resultado final. –

3

A veces quiere tener una enumeración de banderas que represente múltiples opciones; en casos como ese, no es un error. He aquí un ejemplo común:

[Flags] 
public enum FilePermissions 
{ 
    None = 0, 
    Read = 1, 
    Write = 2, 
    Execute = 4, 

    ReadWrite = 3, // Read | Write, 
    ReadWriteExecute = 7 // Read | Write | Execute 
} 

Tal vez debido a la necesidad de apoyar los casos como estos, es por eso que un compilador no causa una advertencia o un error.

+0

Puedo ver las razones por las que el compilador no lo hace (también piensa en la compatibilidad con versiones anteriores, complejidad injustificada, etc.) así que estoy bien que no reciba una advertencia del compilador. Pero todavía estoy buscando una manera de ser advertido. En casos como el suyo, si el uso es válido, puede deshabilitar la inspección con algo como el atributo 'SuppressMessage'. –

+0

También puede tener banderas más elaboradas. Por ejemplo '{Ver = 1, Alter = 2, Acción = 4 | Ver | Alterar} ': de este modo para actuar un elemento que necesita Ver y Alterar; además del derecho en sí mismo. –

3

Nunca lo intenté yo mismo, pero tal vez podría escribir una regla personalizada para FxCop.

Verificar FxCop and Code Analysis: Writing Your Own Custom Rules.

+0

Gracias, eso parece muy prometedor.Podría seguir con la respuesta de Jon Skeet sólo porque creo que va a ser más rápido en el corto plazo para escribir una prueba unitaria en lugar de aprender cómo escribir una regla de FxCop personalizado. –