C#

Lesson 07

LINQ query intent

Use LINQ when the chain reads as a clear query, and avoid mixing filtering with side effects.

Good Code

src/ReviewQueries.cs
public static IReadOnlyList<ReviewSummary> PassingReviews(
    IEnumerable<Review> reviews)
{
    // LINQ reads as filter, sort, then project.
    return reviews
        .Where(review => review.Score >= 70)
        .OrderByDescending(review => review.Score)
        .Select(review => ReviewSummary.From(review))
        .ToList();
}

Bad Code

ReviewQueries.cs
public static IReadOnlyList<ReviewSummary> PassingReviews(IEnumerable<Review> reviews)
{
    var audit = new List<string>();

    // Side effects inside LINQ make the query hard to reason about.
    return reviews
        .Where(review => { audit.Add(review.Id.ToString()); return review.Score >= 70; })
        .Select(review => ReviewSummary.From(review))
        .ToList();
}

Review Notes

What to review

Good Code

The good version reads as a query: filter, sort, project, materialize. Each LINQ method has one visible purpose.

Bad Code

The bad version hides audit mutation inside Where. The expression looks like a query but also writes to an external collection.

Takeaways

  • LINQ works best when each step names a collection transformation, not when the query hides mutation or logging.