Good Code
The good version reads as a query: filter, sort, project, materialize. Each LINQ method has one visible purpose.
Lesson 07
Use LINQ when the chain reads as a clear query, and avoid mixing filtering with side effects.
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();
}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();
}The good version reads as a query: filter, sort, project, materialize. Each LINQ method has one visible purpose.
The bad version hides audit mutation inside Where. The expression looks like a query but also writes to an external collection.