When is it appropriate to use a fall-through (classic) switch statement? Is such usage recommended and encouraged or should it be avoided at all costs?
7 Answers
Here's an example where it would be useful.
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;
}
This sort of thing (where one case includes the other) is rather rare, I think, which is why some newer languages either don't allow fallover or require special syntax for it.
- 2,796
I use them when certain functionality has to be applied for more than one value. For example, say you had an object with a property called operationCode. If the code equals 1, 2, 3 or 4, you want to startOperationX(). If it's 5 or 6, you want to startOperationY() and 7 you startOperationZ(). Why have 7 complete cases with functionality and breaks when you can use fall-throughs?
I think it's completely valid in certain situations, especially if it avoids 100 if-else statements. =)
- 335
Fall-through cases are perfectly fine. I often find that an enumeration is used in lots of places, and that when you don't need to differentiate some cases it is easier to use fall-through logic.
For example (note the explanatory comments):
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;
}
}
I find this kind of use perfectly acceptable.
- 829
I've used them occasionally, I think its always appropriate usage - but only when included with the appropriate comment.
- 48,749
- 7
- 106
- 173
It depends on:
- your personal preference
- your employer's coding standards
- the amount of risk involved
The two main problems associated with letting one case fall through to the next are:
It makes your code dependent on the order of the case statements. That's not the case if you never fall through, and it adds a degree of complexity that's often unwelcome.
It's not obvious that the code for one case includes the code for one or more subsequent cases.
Some places explicitly prohibit falling through. If you don't work at such a place, and if you're comfortable with the practice, and if breaking the code in question won't cause any real suffering, then it might not be the worst thing in the world. If you do it, though, be sure to put an attention-grabbing comment nearby to warn those who come later (including the future you).
- 39,298
Here's a quick (admittedly incomplete (no special handling of leap year)) example of fall-through making my life simpler:
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;
}
- 161
If I feel a need to go from one case to another (rare, admittedly), I prefer to be very explicit and goto case, of course, that assumes your language supports it.
Because falling thru is so uncommon, and very easy to overlook while reading code, I feel it is appropriate to be explicit - and a goto, even if it's to a case, should stand out like a sore thumb.
It also helps avoid bugs that may occur when case statements are reordered.
- 5,860