Loop Condition Never True

ID

csharp.loop_condition_never_true

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

CSharp

Tags

dead-code, loop, reliability

Description

Reports a for loop whose condition is already false when the loop is entered, so its body never runs: for (int i = 0; i < 0; i)`, `for (int i = 5; i < 5; i), for (int i = 0; i > 10; i++).

Rationale

A loop whose condition fails on entry is a block of code that looks live but never executes. Nothing warns about it, tests that cover the surrounding method still pass, and the body silently contributes nothing — the effect the author expected simply does not happen. The usual causes are an off-by-one edit to the bound, a copy-paste that left the wrong comparison operator, and a starting value that was changed without revisiting the condition.

The rule fires only where both values are known from the loop header itself: the header gives a variable an integer literal value — by declaring it, or by assigning to one declared just above the loop — and the condition compares that same variable against another integer literal. A header declaring several variables is read in full, so the condition may name any of them. A bound or a starting value that is computed elsewhere is not analysed, so what the rule reports is decided, not guessed.

public void NeverRuns()
{
    for (int i = 0; i < 0; i++)          // FLAW — 0 < 0 is false; the body is dead
    {
        Log(i);
    }
}

public void NeverRunsEqualBound()
{
    for (int i = 5; i < 5; i++)          // FLAW — 5 < 5 is false; `<=` was probably meant
    {
        Log(i);
    }
}

public void RunsOnce()
{
    for (int i = 0; i <= 0; i++)         // OK — runs for i == 0
    {
        Log(i);
    }
}

public void RunsToBound(int limit)
{
    for (int i = 0; i < limit; i++)      // OK — the bound is not known here
    {
        Log(i);
    }
}

Remediation

Work out which of the two values is wrong. If the body is meant to run for the starting value, widen the comparison (i ⇐ 5 rather than i < 5) or correct the bound. If the comparison operator points the wrong way, flip it. If the loop is genuinely obsolete, delete it along with its body rather than leaving unreachable code behind.