What's the best practice for using a switch
statement vs using an if
statement for 30 unsigned
enumerations where about 10 have an expected action (that presently is the same action). Performance and space need to be considered but are not critical. I've abstracted the snippet so don't hate me for the naming conventions.
switch
statement:
// numError is an error enumeration type, with 0 being the non-error case
// fire_special_event() is a stub method for the shared processing
switch (numError)
{
case ERROR_01 : // intentional fall-through
case ERROR_07 : // intentional fall-through
case ERROR_0A : // intentional fall-through
case ERROR_10 : // intentional fall-through
case ERROR_15 : // intentional fall-through
case ERROR_16 : // intentional fall-through
case ERROR_20 :
{
fire_special_event();
}
break;
default:
{
// error codes that require no additional action
}
break;
}
if
statement:
if ((ERROR_01 == numError) ||
(ERROR_07 == numError) ||
(ERROR_0A == numError) ||
(ERROR_10 == numError) ||
(ERROR_15 == numError) ||
(ERROR_16 == numError) ||
(ERROR_20 == numError))
{
fire_special_event();
}
I'm not sure about best-practise, but I'd use switch - and then trap intentional fall-through via 'default'
I would pick the if statement for the sake of clarity and convention, although I'm sure that some would disagree. After all, you are wanting to do something
if
some condition is true! Having a switch with one action seems a little... unneccesary.switch is definitely preferred. It's easier to look at a switch's list of cases & know for sure what it is doing than to read the long if condition.
The duplication in the
if
condition is hard on the eyes. Suppose one of the==
was written!=
; would you notice? Or if one instance of 'numError' was written 'nmuError', which just happened to compile?I'd generally prefer to use polymorphism instead of the switch, but without more details of the context, it's hard to say.
As for performance, your best bet is to use a profiler to measure the performance of your application in conditions that are similar to what you expect in the wild. Otherwise, you're probably optimizing in the wrong place and in the wrong way.
Probably the first one is optimised by the compiler, that would explain why the second loop is slower when increasing loop count.
For the special case that you've provided in your example, the clearest code is probably:
Obviously this just moves the problem to a different area of the code, but now you have the opportunity to reuse this test. You also have more options for how to solve it. You could use std::set, for example:
I'm not suggesting that this is the best implementation of RequiresSpecialEvent, just that it's an option. You can still use a switch or if-else chain, or a lookup table, or some bit-manipulation on the value, whatever. The more obscure your decision process becomes, the more value you'll derive from having it in an isolated function.
Compiler will optimise it anyway - go for the switch as it's the most readable.