Control Statement Braces

ID

csharp.control_statement_braces

Severity

info

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Best Practice

Language

CSharp

Tags

best-practice

Description

Reports two related defects. First, if, else, while, for, foreach and do control statements whose body is a single statement written without surrounding braces. Second, the statement that follows such an unbraced control statement when it is indented as though it were part of the body, even though it runs unconditionally.

Rationale

Unbraced body. An unbraced control-statement body is fragile. When a second statement is added later it silently falls outside the control flow even though the indentation suggests otherwise — the "goto fail" family of bugs. Always bracing the body also keeps debug-stepping aligned with the condition and removes any ambiguity about which statements the branch or loop covers.

Misleadingly indented continuation. The same bug, already committed. C# ignores layout, so only the first statement after an unbraced if belongs to it; a second statement indented to the same column runs on every path regardless of the condition. Nothing in the compiler complains, and the indentation actively hides the mistake from reviewers, who read the block as the author intended it rather than as the language defines it. This is reported only when the control statement has no braces — a braced body states its extent explicitly and cannot mislead — and only when the following statement starts on a later line at or past the column of the body.

if (ready)
    Start();                 // FLAW, unbraced if body

while (HasNext())
    Advance();               // FLAW, unbraced while body

for (int i = 0; i < n; i++)
    Process(i);              // FLAW, unbraced for body

if (ready)
    Start();                 // FLAW, unbraced if body
    Log("started");          // FLAW, indented like the body but runs unconditionally

if (ready)
{
    Start();                 // OK
    Log("started");          // OK, the braces say what belongs to the branch
}

if (ready)
    Start();                 // FLAW, unbraced if body
Log("started");              // OK, the layout matches what the code does

Remediation

Wrap the body in a block with { }, even when it currently contains a single statement. Where a following statement is indented as if it belonged to the body, decide which behaviour was meant: move it inside the new block if it should be conditional, or outdent it to the level of the control statement if it should not.