Why is "else" rarely used after "if x then return"?
This method:
boolean containsSmiley(String s) {
if (s == null) {
return false;
}
else {
return s.contains(":)");
}
}
can equivalently be written:
boolean containsSmiley(String s) {
if (s == null) {
return false;
}
return s.contains(":)");
}
In my experience, the second form is seen more often, especially in more complex methods (where there may be several such exit points), and the same is true for "throw" as well as "return". Yet the first form arguably makes the conditional structure of the code more explicit. Are there any reasons to prefer one over the other?
(Related: Should a function have only one return statement?)
The else
in that case would be redundant, as well as create unnecessary extra indentation for the main code of the function.
In my experience, it depends on the code. If I'm 'guarding' against something, I'll do:
if (inputVar.isBad()) {
return;
}
doThings();
The point is clear: If that statement is false, I don't want the function to continue.
On the other hand, there are some functions with multiple options, and in that case I would write it like this:
if (inputVar == thingOne) {
doFirstThing();
} else if (inputVar == secondThing) {
doSecondThing();
} else {
doThirdThing();
}
Even though it could be written as:
if (inputVar == thingOne) {
doFirstThing();
return;
}
if (inputVar == thingTwo) {
doSecondThing();
return;
}
doThingThree();
return;
It really comes down to which way most clearly shows what the code is doing (not necessarily which bit of code is shortest or has the least indentation).
This is a pattern called Guard Clause. The idea is do all the checking upfront to reduce nested conditions to increase readability.
From the link:
double getPayAmount() {
double result;
if (_isDead) {
result = deadAmount();
} else {
if (_isSeparated) {
result = separatedAmount();
} else {
if (_isRetired) {
result = retiredAmount();
} else {
result = normalPayAmount();
}
}
}
return result;
}
Using the Guard Clause, you'll get to see this result:
double getPayAmount() {
if (_isDead) return deadAmount();
if (_isSeparated) return separatedAmount();
if (_isRetired) return retiredAmount();
return normalPayAmount();
};
You will see this all over:
if (condition) {
return var;
}
// by nature, when execution reaches this point, condition can only be false,
// therefore, the else is unnecessary
return other_var;
Most of the time the addition of an else clause is not only unnecessary in this case, but a lot of times, it gets optimized away by the compiler.
Think of how the computer thinks of this code (in terms of machine code, simplified into pseudocode here for demonstration purposes):
0x00: test [condition]
0x01: if result of test was not true, goto [0x04]
0x02: push [var] onto stack
0x03: goto [0x05]
0x04: push [other_var] onto stack
0x05: return from subroutine
The code (again, this is a pseudocode and not assembly) would act the exact same way for an if/then/else
conditional.
It is, by many people, considered bad and/or confusing practice to have multiple possible exit points for a function, as a programmer must think of every possible path through his code. Another practice is the following:
return (condition) ? var : other_var;
This simplifies the code, and does not create any new exit points.