triple tipos simple luz interruptores interruptor instalar electricos electrico cruce conmutadores conmutador conmutacion como c#

c# - tipos - interruptores y conmutadores



¿Hay alguna manera de hacer que el compilador C#emita un error si a un conmutador(enum_val) le falta una declaración de caso? (8)

Con solo tirar (no intencionadamente) esto, puede reemplazar el Switch-Case con un diccionario ( Func<int,int> como ejemplo):

Dictionary<Colors,Func<int,int>> d = new Dictionary<Colors, Func<int, int>>(); d.Add(Colors.Red, (x) => x+1); d.Add(Colors.Blue, (x) => x+1); d.Add(Colors.Green, (x) => x+1); foreach (Colors color in Enum.GetValues(typeof(Colors))) { if (!d.ContainsKey(color)) { throw new Exception("Poor color " + color + " ignored"); } }

Acabo de darme cuenta de que agregué un valor a la lista de valores "obligatorios" en mi enumeración, pero no lo detecté hasta el tiempo de ejecución. Sé que el compilador de C # es realmente poderoso cuando se trata de la reflexión y la introspección de tipos, por lo que me preguntaba si habría una manera de forzar una declaración switch / case para cubrir todos los valores de enum posibles.

Ejemplo:

enum Colors { Red, Blue, Green, Yellow }; Colors c = ...; switch (c) { case Colors.Red: // No error, Red is a Color break; case Colors.Blue: case Colors.Green: // No error, Blue and Green handled as well break; } // whoops! "error: ''Colors.Yellow'' unhandled" // or even, "error: no ''default'' and ''Colors.Yellow'' unhandled"

Quiero una solución en tiempo de compilación.


El compilador de C # no tiene esta comprobación incorporada, pero hay un verificador de contratos de código para .Net que lo tiene: https://blogs.msdn.microsoft.com/francesco/2014/09/12/how-to-use-cccheck-to-prove-no-case-is-forgotten/

La técnica es usar una aserción de contrato de código para decirle al verificador que el caso default nunca debe ser accesible:

switch (c) { case Colors.Red: break; case Colors.Blue: case Colors.Green: break; default: Contract.Assert(false); // Tell static checker this shouldn''t happen }

Luego, si el verificador ve que es alcanzable (porque no se maneja uno de los valores de enumeración), le avisará:

warning : CodeContracts: This assert, always leading to an error, may be reachable. Are you missing an enum case?


Este es exactamente el mejor ejemplo de por qué necesitamos pruebas en todas las soluciones. Debe escribir una prueba que pueda enumerar su Enum y llamar a ese método que contiene el caso del interruptor. Con esta prueba, obtendrá una prueba fallida cada vez que edite el Enum, pero olvide actualizar la caja del interruptor.

[Test] public void CheckThatAllEnumCoveredInSwitchCase() { foreach (var singleEnum in Enum.GetValues(typeof(YOURENUM))) { myclass.methodofswitchcase((YOURENUM)singleEnum); } }


No, no hay una forma de compilación para que esto suceda. Sin embargo, la respuesta MUY simple es tener un controlador default que simplemente arroje una excepción en el sentido de "esta opción no se manejó, abucheo".

switch (c) { case Colors.Red: // no error, Red is a Color break; case Colors.Blue: case Colors.Green: // no error, Blue and Green handled as well break; default: throw new Exception("Unhandled option: " + c.ToString()); }


Para C ++ puede hacer que el compilador emita una advertencia agregando el conmutador / we4061 del compilador a la configuración de su proyecto. Espero que esto ayude. :)

http://msdn.microsoft.com/en-us/library/thxezb7y.aspx

http://msdn.microsoft.com/en-us/library/96f5t7fy(v=vs.80).aspx

En realidad estaba equivocado acerca de esto; parece que puede hacer que el compilador lance un error. Solo compila con / Wall / we4061. No lo he intentado yo mismo, pero al leer las páginas de MSDN anteriores, parece que esto debería funcionar.


Podría lanzar una excepción al principio si el tamaño de la enumeración, es de esperar que le avise muy pronto cuando se haya realizado un cambio en la enumeración:

enum MyEnum {A, B}; class TestEnum { // Static constructor static TestEnum() { // Check if this code needs updating as the enum has changed if (Enum.GetNames(typeof(MyEnum)).Length != 2) { // If this fails update myFunction and the number above throw new Exception("Internal error - code inconsistency"); } } // My function that switches on the enum string myFunction(MyEnum myEnum) { switch (myEnum) { case MyEnum.A: return "A"; case MyEnum.B: return "B"; } throw new Exception("Internal error - missing case"); } }

Esto generará una excepción desde el constructor estático si se modifica la cantidad de elementos en la enumeración. Así que el desarrollador sabe que necesita actualizar el código. Incluso podría hacer esta verificación desde una prueba de unidad que ejecute con su compilación.


Puede usar SwitchEnumAnalyzer para obtener advertencias de compilación de este tipo. Lo acabo de usar en mi proyecto y funciona muy bien. Como en cualquier analizador de Roslyn, puede elegir el nivel de notificación, si es solo una advertencia, o un error adecuado.