Si estoy usando una instrucción switch para manejar valores de una enumeración (que es propiedad de mi clase) y tengo un caso para cada valor posible, ¿vale la pena agregar código para manejar el caso "predeterminado"?
enum MyEnum
{
MyFoo,
MyBar,
MyBat
}
MyEnum myEnum = GetMyEnum();
switch (myEnum)
{
case MyFoo:
DoFoo();
break;
case MyBar:
DoBar();
break;
case MyBat:
DoBat();
break;
default:
Log("Unexpected value");
throw new ArgumentException()
}
No creo que sea porque este código nunca se puede alcanzar (incluso con pruebas unitarias). Mi compañero de trabajo no está de acuerdo y cree que esto nos protege contra comportamientos inesperados causados por la adición de nuevos valores a MyEnum.
¿Qué dices, comunidad?
unit-testing
maintenance
enum
Dakota del Sur
fuente
fuente
MyEnum
luego pasarlo a través de su interruptor?switch
completo la declaración.Respuestas:
La inclusión del caso predeterminado no cambia la forma en que funciona su código, pero hace que su código sea más fácil de mantener. Al hacer que el código se rompa de una manera obvia (registrar un mensaje y lanzar una excepción), está incluyendo una gran flecha roja para el interno que su empresa contrata el próximo verano para agregar un par de características. La flecha dice: "¡Hola, sí! ¡Estoy hablando con USTED! Si va a agregar otro valor a la enumeración, será mejor que agregue un caso aquí también". Ese esfuerzo adicional podría agregar algunos bytes al programa compilado, que es algo a considerar. Pero también salvará a alguien (tal vez incluso el futuro) en algún lugar entre una hora y un día de rascado improductivo.
Actualización: el compilador también puede detectar la situación descrita anteriormente, es decir, proteger contra los valores agregados a una enumeración en algún momento posterior. Clang (y gcc, creo) emitirá una advertencia de forma predeterminada si activa un tipo enumerado pero no tiene un caso que cubra todos los valores posibles en la enumeración. Entonces, por ejemplo, si elimina el
default
caso de su conmutador y agrega un nuevo valorMyBaz
a la enumeración, recibirá una advertencia que dice:Dejar que el compilador detecte casos no cubiertos es que elimina en gran medida la necesidad de ese
default
caso inalcanzable que inspiró su pregunta en primer lugar.fuente
También estuve hablando con un compañero de trabajo sobre esto esta mañana; es realmente desafortunado, pero creo que manejar el valor predeterminado es necesario por seguridad, por dos razones:
Primero, como menciona su compañero de trabajo, protege el código del futuro contra los nuevos valores que se agregan a la enumeración. Esto puede o no parecer una posibilidad, pero siempre está ahí.
Más importante aún, dependiendo del idioma / compilador, puede ser posible tener valores que no sean miembros de la enumeración en su variable conmutada. Por ejemplo, en C #:
Al agregar lo simple
case default:
y lanzar una excepción, se ha protegido contra este caso extraño en el que "nada" sucede pero "algo" debería haber sucedido.Desafortunadamente, básicamente cada vez que escribo una declaración de cambio, es porque estoy revisando los casos de una enumeración. Realmente desearía que el lenguaje "aplicara el comportamiento de" lanzar por defecto "(al menos agregando una palabra clave).
fuente
Agregar un caso predeterminado, incluso si nunca espera alcanzarlo, puede ser algo bueno. Hará la depuración mucho más fácil si su código arroja una excepción "Esto no debería haber sucedido" de inmediato en lugar de más adelante en el programa, arrojando alguna excepción misteriosa o devolviendo resultados inesperados sin error.
fuente
Yo digo:
Intenta agregar otro tipo a
MyEnum
. Luego cambia esta línea:a
Luego, ejecute su código con el caso predeterminado y sin el caso predeterminado. ¿Qué comportamiento prefieres?
Tener el caso predeterminado también puede ser útil para atrapar
NULL
valores y prevenirlosNullPointerExceptions
.fuente
Si tuviera alguna idea de cómo se puede ahorrar tiempo de máquina insistiendo en el caso predeterminado, no necesitaría hacer la pregunta. Silenciosamente no hacer nada en una condición de error no es aceptable: ¿detecta silenciosamente excepciones que nunca deberían suceder? Dejar "minas" para los programadores que te siguen, igualmente inaceptable.
Si su código nunca se va a cambiar o modificar, y está 100% libre de errores, omitir el caso predeterminado puede estar bien.
Ada (el abuelo de los lenguajes de programación robustos) no compilará un conmutador en una enumeración, a menos que todas las enumeraciones estén cubiertas o haya un controlador predeterminado: esta función está en mi lista de deseos para cada idioma. Nuestro estándar de codificación Ada establece que con los conmutadores en las enumeraciones, el manejo explícito de todos los valores, sin valores predeterminados, es la forma preferida de manejar esta situación.
fuente