Meaningless Size Comparison

ID

csharp.meaningless_size_comparison

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

CSharp

Tags

collection, reliability, suspicious-comparison

Description

Reports a collection size or array length compared against a bound the size can never cross, which makes the comparison a constant. Count, Length, LongLength and the Count() sequence extension all report how many elements there are and none of them can be negative, so >= 0 and > -1 always hold, while < 0 and ⇐ -1 never do.

Rationale

A comparison that cannot change its answer is either a guard that guards nothing or — far more often — an emptiness check that was written with the wrong bound. if (items.Count >= 0) reads like "if there is anything in the list" and behaves like "always", so the code inside runs for the empty list too and the bug surfaces later as an index out of range or an empty report. The mirrored form if (0 > items.Count) has the opposite failure: the branch is dead, and whatever it was supposed to handle is silently never handled.

Both operand orders are recognised. Only the bounds 0 and -1 are considered — every positive bound expresses a real condition. Matching is by member name on a receiver, so a plain identifier named Count belonging to the enclosing type is not treated as a size.

public class Cart
{
    private readonly List<string> items = new List<string>();
    private readonly int[] slots = new int[8];

    public void Report()
    {
        if (items.Count >= 0)          // FLAW — always true, the guard does nothing
        {
            Console.WriteLine(items[0]);
        }

        if (slots.Length < 0)          // FLAW — always false, this branch is dead
        {
            Console.WriteLine("no slots");
        }

        if (slots.LongLength >= 0)     // FLAW — the 64-bit length is never negative either
        {
            Console.WriteLine(slots[0]);
        }

        if (items.Count > 0)           // OK — genuine emptiness check
        {
            Console.WriteLine(items[0]);
        }

        if (slots.Length >= 2)         // OK — a real bound
        {
            Console.WriteLine(slots[1]);
        }
    }
}

Remediation

Decide what the test was meant to say and write that bound. "Has elements" is Count > 0 (or Count != 0); "is empty" is Count == 0. For a sequence, prefer Any() over Count() > 0, as it stops at the first element. If the comparison was defensive and the value genuinely cannot be negative, delete it — it adds no protection and hides the reader’s eye from the checks that do.