¿Cuándo es apropiado usar una declaración de cambio fallido (clásico)? ¿Se recomienda y alienta tal uso o debe evitarse a toda costa?
¿Cuándo es apropiado usar una declaración de cambio fallido (clásico)? ¿Se recomienda y alienta tal uso o debe evitarse a toda costa?
Respuestas:
Aquí hay un ejemplo donde sería útil.
public Collection<LogItems> GetAllLogItems(Level level) {
Collection<LogItems> result = new Collection<LogItems>();
switch (level) {
// Note: fall through here is INTENTIONAL
case All:
case Info:
result.Add(GetItemsForLevel(Info));
case Warning:
result.Add(GetItemsForLevel(Warning));
case Error:
result.Add(GetItemsForLevel(Error));
case Critical:
result.Add(GetItemsForLevel(Critical));
case None:
}
return result;
}
Creo que este tipo de cosas (donde un caso incluye el otro) es bastante raro, por lo que algunos idiomas más nuevos no permiten Falla o requieren una sintaxis especial para ello.
// INTENTIONAL FALL THROUGH HERE
comentario de mayúsculas requerido .
GetItemsForLevel(Info)
hacer que se invoque la llamada, GetItemsForLevel(Warning)
etc.
Los uso cuando se debe aplicar cierta funcionalidad para más de un valor. Por ejemplo, supongamos que tenía un objeto con una propiedad llamada operationCode. Si el código es igual a 1, 2, 3 o 4, desea iniciar OperationX (). Si es 5 o 6, desea iniciar OperaciónY () y 7 inicia OperaciónZ (). ¿Por qué tener 7 casos completos con funcionalidad y pausas cuando puede usar fall-throughs?
Creo que es completamente válido en ciertas situaciones, especialmente si evita 100 declaraciones if-else. =)
switch
con múltiples case
s vinculados al mismo código. Eso es diferente a un fracaso, donde la ejecución de uno case
continúa en el siguiente debido a la falta de un break
entre ellos.
Los casos de caída están perfectamente bien. A menudo encuentro que una enumeración se usa en muchos lugares, y que cuando no es necesario diferenciar algunos casos, es más fácil usar la lógica de caída.
Por ejemplo (tenga en cuenta los comentarios explicativos):
public boolean isAvailable(Server server, HealthStatus health) {
switch(health) {
// Equivalent positive cases
case HEALTHY:
case UNDER_LOAD:
return true;
// Equivalent negative cases
case FAULT_REPORTED:
case UNKNOWN:
case CANNOT_COMMUNICATE:
return false;
// Unknown enumeration!
default:
LOG.warn("Unknown enumeration " + health);
return false;
}
}
Este tipo de uso me parece perfectamente aceptable.
case X: case Y: doSomething()
y case X: doSomething(); case Y: doAnotherThing()
. En el primero, la intención es bastante explícita, mientras que en el segundo, la caída puede ser intencional o no. En mi experiencia, el primer ejemplo nunca activa advertencias en compiladores / analizadores de código, mientras que el segundo sí. Personalmente, solo llamaría al segundo ejemplo "caer", aunque no estoy seguro de una definición "oficial".
Depende de:
Los dos problemas principales asociados con dejar que un caso caiga al siguiente son:
Hace que su código dependa del orden de las declaraciones de casos. Ese no es el caso si nunca se cae, y agrega un grado de complejidad que a menudo no es bienvenido.
No es obvio que el código para un caso incluye el código para uno o más casos posteriores.
Algunos lugares prohíben explícitamente la caída. Si no trabaja en ese lugar, y si se siente cómodo con la práctica, y si descifrar el código en cuestión no causará ningún sufrimiento real, entonces podría no ser lo peor del mundo. Sin embargo, si lo haces, asegúrate de poner un comentario que llame la atención cerca para advertir a los que vengan después (incluido tu futuro).
Aquí hay un ejemplo rápido (admitidamente incompleto (sin manejo especial del año bisiesto)) de fallas que simplifican mi vida:
function get_julian_day (date) {
int utc_date = date.getUTCDate();
int utc_month = date.getUTCMonth();
int julian_day = 0;
switch (utc_month) {
case 11: julian_day += 30;
case 10: julian_day += 31;
case 9: julian_day += 30;
case 8: julian_day += 31;
case 7: julian_day += 31;
case 6: julian_day += 30;
case 5: julian_day += 31;
case 4: julian_day += 30;
case 3: julian_day += 31;
case 2: julian_day += 28;
case 1: julian_day += 31;
default: break;
}
return julian_day + utc_date;
}
Si siento la necesidad de pasar de un caso a otro (raro, lo admito), prefiero ser muy explícito y goto case
, por supuesto, eso supone que su idioma lo respalde.
Debido a que caer es muy poco común y muy fácil de pasar por alto al leer el código, creo que es apropiado ser explícito, y un goto, incluso si es un caso, debería destacarse como un pulgar dolorido.
También ayuda a evitar errores que pueden ocurrir cuando se reordenan las declaraciones de casos.