Conditionals Start New Lines
ID |
csharp.conditionals_start_new_lines |
Severity |
high |
Remediation Complexity |
medium |
Remediation Risk |
low |
Remediation Effort |
medium |
Resource |
Code Smell |
Language |
CSharp |
Tags |
code_smell, readability, suspicious-control-flow |
Description
Reports an if statement that starts on the very line where the preceding if statement ended, so
that a closing brace and the next condition share a line.
The test is positional: the if begins on the line where its immediately preceding sibling
statement ended, and that sibling is itself an if. A genuine else if is never reported — it
belongs to the outer if rather than following it — and neither is an if preceded by any other
kind of statement, because only a neighbouring conditional creates the ambiguity this rule is
about.
Rationale
Two conditionals written on one line look like a single construct. A reader scanning the left
margin sees one decision and takes the second condition for an else if, all the more so because a
closing brace is exactly what an else if normally follows. They are independent statements: both
conditions are evaluated, and both bodies run when both hold.
That makes the formatting harmful in either direction. If the two conditions were meant to be
alternatives, the missing else is a live bug and the layout is hiding it. If they were meant to be
independent, the layout hides that the first branch falls through into the second — precisely the
fact a reader needs in order to reason about what happens when both conditions are true. A line
break costs nothing and settles the question for good.
public class Router
{
public string Route(int code, bool urgent)
{
if (code == 1)
{
Log("one");
} if (code == 2) // FLAW - reads as else if; both conditions run
{
Log("two");
}
if (urgent)
{
Log("urgent");
}
if (code > 100) // OK - on its own line, clearly independent
{
Log("large");
}
if (code == 3)
{
return "three";
}
else if (code == 4) // OK - a real else branch
{
return "four";
}
return "none";
}
private void Log(string message) { }
}
Remediation
Decide which of the two readings is intended and write it. If the conditions are alternatives, join
them with else — that also stops the second condition being evaluated once the first has matched.
If they are genuinely independent checks, move the second if onto its own line so the fall-through
is visible. Where a chain of independent conditions on one value is really a dispatch, a switch
statement or a switch expression states that better than either form.