Multiple OrderBy

ID

csharp.multiple_orderby

Severity

low

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

CSharp

Tags

linq, reliability

Description

Reports a LINQ chain that calls OrderBy (or OrderByDescending) twice in succession. The second call re-sorts the sequence from scratch and discards the first ordering, so only the last criterion is actually applied. A multi-key sort is expressed with ThenBy / ThenByDescending.

Rationale

OrderBy returns a sequence whose elements are arranged by a single key. Calling OrderBy again on the result repeats that — every element is repositioned by the new key alone, with no memory of the previous one. The intent of "sort by A and then by B" is what ThenBy exists for; using OrderBy.OrderBy silently produces a different result.

using System.Linq;
using System.Collections.Generic;

public class Sorter
{
    public IEnumerable<Person> Bad(IEnumerable<Person> people) =>
        people.OrderBy(p => p.LastName)           // FLAW — sort lost by the next OrderBy
              .OrderBy(p => p.FirstName);

    public IEnumerable<Person> Good(IEnumerable<Person> people) =>
        people.OrderBy(p => p.LastName)           // OK — secondary sort via ThenBy
              .ThenBy(p => p.FirstName);
}

Remediation

Replace the second (and any subsequent) OrderBy in the chain with ThenBy, and OrderByDescending with ThenByDescending. The primary OrderBy stays as the first call.

References