- Feb 8, 2004
- 12,604
- 15
- 81
Is there any advantage to if-else statements or nesting if's when a group of say 5 or so if's will do the same job and likely be more readable?
The less nesting, the better.
I would expect any halfway sane compiler to compile your two logically equivalent code examples identically. The latter is only better because it has less nesting and is therefore easier for a human to read - it's not an optimization.
I would expect any halfway sane compiler to compile your two logically equivalent code examples identically. The latter is only better because it has less nesting and is therefore easier for a human to read - it's not an optimization.
I was talking about how to arrange logically equivalent code, of course. I'll use your example to illustrate:Not always true. Lets say you are doing collision detection in which you want to know if a bullet passes through one of the planes of a 3d model. One of the simplest ways to do this check is to surround the model with a sphere and then check if the bullet is inside the sphere. This is a VERY quick calculation. Running this check first and then the real collision detection if it fails will save a ton of processing time.
// More nesting - usually bad
if (quickCheck())
{
for (...)
{
while (...)
{
...
}
...
}
}
else
return NOHIT;
// Less nesting - usually good
if (!quickCheck())
return NOHIT;
for (...)
{
while (...)
{
...
}
...
}
The choice of nested ifs versus else ifs versus ifs with several clauses connected with logical operators has almost nothing to do with performance.Nesting done wrong can be slow, but done right it can really boost the codes speed. (The right way is to use simple calculations to check if complex calculations are necessarily).
// Do this check first, since we can avoid I/O
if (0 == x) {
...
} else if (ThingThatMightDoBlockingIO()) {
..
}
Optimize your control structures for readability. Have a really, really good reason if you decide to do one if before another for "performance reasons", and call it out explicitly if you do so, e.g.,
Code:// Do this check first, since we can avoid I/O if (0 == x) { ... } else if (ThingThatMightDoBlockingIO()) { .. }
... but if all the predicates are simple, the organization of the control flow itself (nested if/else, successive if, etc.) often doesn't matter. So much so that if you have to ask, it probably doesn't matter.
bool blockingIO = ThingThatMightDoBlockingIO();
int value = 0;
if (0 == x)
{ // Do this check first, since we can avoid I/O
value = 1;
}
else if (blockingIO)
{
value = 2;
}
return value;
The things I don't like about this:Off topic a little bit...
For readability I would prefer to code this in the following manner...
I am ok with code that is a bit more wordy but anyone, I think, can read it.
This is my preference and in no way I'm saying it is the better way.
I prefer boolean checks to have their variable since long method names can get confusing inside if statements.
I also prefer to include comments inside the if statement, if possible. Some programmers might copy and paste a block of code and forget to copy comments. In this manner, the comments are forced.
I also prefer code that has a single return path. Multiple return paths are a pain when debugging.
Code:bool blockingIO = ThingThatMightDoBlockingIO(); int value = 0; if (0 == x) { // Do this check first, since we can avoid I/O value = 1; } else if (blockingIO) { value = 2; } return value;
The things I don't like about this:
1. Your code doesn't avoid possibly unnecessary I/O blocking check. It's the first thing it does! Unless the compiler is really smart and can figure out that it can postpone setting blockingIO.
2. The norm is to put a comment before the code. If the first line wasn't "value=1" but some other if-statement, it could be easily confusing to know which one are you commenting.
3. In the light of 1, the comment isn't even correct.
4. If a function is named properly and used only once, assigning a result to boolean doesn't do much for readibility to me.
bool blockingIO = ThingThatMightDoBlockingIO();
int value = 0;
if (blockingIO)
{ // Comment here
value = 1;
}
else if (x == 0)
{
value = 2;
}
else
{
value = 3;
}
return value;
You are better off using switch/case if you can rather than a bunch of if statements.
The output from switch/case is often cleaner assembly than a bunch of if.
One thing I find strange is that in some scripting languages like php using a bunch of if statements is actually faster than using a switch statement. (Providing your bunch of if statements are making a classic mistake like calling a function)
I still don't understand that.
where $someobject->method is some fairly complicated calculation (like a sql query with a long runtime).
They seem kinda dumbfounded as to why you would want to only run the method once and just compare the result 3 times.
You're still having the same performance problem. You want something like:I don't disagree with your comments as it is a bad illustration. Regarding # 4 ... it is quite subjective.
I did not take any time to make it better according how to I like to code...but let's tweak it a bit.
Code:bool blockingIO = ThingThatMightDoBlockingIO(); int value = 0; if (blockingIO) { // Comment here value = 1; } else if (x == 0) { value = 2; } else { value = 3; } return value;
int value = 0;
// Comment here :)
if (x == 0)
{
value = 1;
}
else
{
bool blockingIO = ThingThatMightDoBlockingIO();
if (blockingIO)
{
value = 2;
}
else
{
value = 3;
}
}
return value;
// first check this to avoid blocking IO
if (x == 0)
{
return 1;
}
if (ThingThatMightDoBlockingIO())
{
return 2;
}
return 3;
Except in RAII capable languages like C++ where you don't need to do any extra work to release things on multiple return paths.Multiple return paths are PITA if you need to release dynamic memory before returning to caller
You're still having the same performance problem. You want something like:
You want to test x==0 before you execute ThingThatMightDoBlockingIO(), so that you can avoid blocking IO if you don't have to. In your code, you never avoid it.Code:int value = 0; if (x == 0) { value = 1; } else { bool blockingIO = ThingThatMightDoBlockingIO(); if (blockingIO) { value = 2; } else { value = 3; } } return value;