How do you optimize LINQ queries?

4 minintermediate.NETLINQperformanceoptimization

Quick Answer

Optimize LINQ by filtering early (`Where` before `Select`/ordering) to shrink the working set, avoiding multiple enumeration of the same deferred query (materialize once with `ToList`), and choosing the right operators (`Any()` instead of `Count() > 0`, `FirstOrDefault` instead of `Where(...).FirstOrDefault()`). For LINQ-to-Entities, keep queries server-side (avoid client evaluation) and project only needed columns. Avoid heavy LINQ in tight CPU loops where a plain loop is cheaper.

Detailed Answer

Optimization Techniques:

1. Use Appropriate Methods

// Bad: Materializing entire collection
if (list.Where(x => x > 5).Count() > 0)

// Good: Short-circuit evaluation
if (list.Any(x => x > 5))

2. Avoid Multiple Enumeration

// Bad: Query executed twice
var query = list.Where(x => x > 5);
var count = query.Count();
var sum = query.Sum();

// Good: Materialize once
var results = list.Where(x => x > 5).ToList();
var count = results.Count;
var sum = results.Sum();

3. Filter Early

// Bad: Select then filter
var result = list.Select(x => new { x.Id, x.Name })
                 .Where(x => x.Id > 100);

// Good: Filter then select
var result = list.Where(x => x.Id > 100)
                 .Select(x => new { x.Id, x.Name });

4. Use Proper Collection Types

// For lookups, use HashSet or Dictionary
var hashSet = new HashSet(largeList);
if (hashSet.Contains(value)) // O(1) instead of O(n)

// For indexed access, use arrays or lists
int[] array = list.ToArray(); // Better than IEnumerable for iteration

5. Avoid Unnecessary Sorting

// Bad: Sort entire collection to get top 10
var top10 = list.OrderBy(x => x.Score).Take(10);

// Good: Use efficient algorithm for top N
var top10 = list.OrderByDescending(x => x.Score).Take(10);
// Or use a priority queue for large datasets

6. Use AsParallel() for Large Datasets

// Sequential
var result = hugeList.Where(x => ExpensiveOperation(x));

// Parallel (for CPU-bound operations)
var result = hugeList.AsParallel()
                     .Where(x => ExpensiveOperation(x));

7. Avoid Closures in Loops

// Bad: Captured variable
for (int i = 0; i < items.Count; i++)
{
    var query = list.Where(x => x.Id == i); // Captures 'i'
}

// Good: Local copy
for (int i = 0; i < items.Count; i++)
{
    var index = i;
    var query = list.Where(x => x.Id == index);
}

8. Use Compiled Queries for Repeated Execution

// Entity Framework example
var compiledQuery = EF.CompileQuery(
    (MyContext ctx, int id) => ctx.Users.Where(u => u.Id == id)
);