What is the difference between `Where().Select()` and `Select().Where()`?

4 minintermediate.NETLINQperformance

Quick Answer

Both produce the same elements, but order affects work done. `Where().Select()` filters first, so the (often more expensive) projection runs only on matching elements — usually more efficient. `Select().Where()` projects every element first, then filters, doing extra transformation work. Filter as early as possible; the exception is when the projection is needed to evaluate the predicate.

Detailed Answer

Both produce the same final result, but they differ in performance and efficiency.

Where().Select() - Filter First, Then Transform

  • Better Performance: Filters data before transformation
  • Fewer operations: Only transforms elements that pass the filter
  • Recommended approach in most cases

Select().Where() - Transform First, Then Filter

  • Worse Performance: Transforms all elements before filtering
  • More operations: Wastes resources on elements that will be filtered out
  • Useful only when the transformation is needed for filtering logic
var numbers = Enumerable.Range(1, 1000);

// WHERE THEN SELECT (Recommended)
var result1 = numbers
    .Where(n => n > 500)           // 1. Filter: 500 elements remain
    .Select(n => n * n);            // 2. Transform: 500 operations

// SELECT THEN WHERE (Less Efficient)
var result2 = numbers
    .Select(n => n * n)             // 1. Transform: 1000 operations
    .Where(n => n > 250000);        // 2. Filter: 500 elements remain

// Both produce the same result, but result1 performs half the transformations!

Performance Comparison:

// Example with complex objects
var users = GetUsers(); // 10,000 users

// EFFICIENT: Filter first
var result1 = users
    .Where(u => u.Age > 18)                          // Filter 10,000 -> 6,000
    .Select(u => new UserDto                         // Transform 6,000 objects
    { 
        FullName = u.FirstName + " " + u.LastName,
        Email = u.Email 
    });

// INEFFICIENT: Select first
var result2 = users
    .Select(u => new UserDto                         // Transform 10,000 objects
    { 
        FullName = u.FirstName + " " + u.LastName,
        Email = u.Email 
    })
    .Where(dto => CalculateAge(dto) > 18);          // Filter 10,000 -> 6,000

// result1 creates 6,000 DTO objects
// result2 creates 10,000 DTO objects (4,000 wasted)

When to Use Each:

Use Where().Select() when:

  • Filter condition uses original object properties
  • You want to minimize transformations
  • Performance matters (almost always)
var activeUsers = users
    .Where(u => u.IsActive)
    .Select(u => u.Name);

Use Select().Where() when:

  • Filter condition requires the transformed data
  • The transformation is necessary for filtering logic
var validEmails = users
    .Select(u => u.Email.Trim().ToLower())
    .Where(email => email.Contains("@company.com"));

// Or even better, combine them:
var validEmails = users
    .Where(u => u.Email != null)
    .Select(u => u.Email.Trim().ToLower())
    .Where(email => email.Contains("@company.com"));

Rule of Thumb: Filter as early as possible in the LINQ chain to reduce the number of elements processed by subsequent operations.

// BEST: Filter -> Filter -> Select
var result = items
    .Where(i => i.IsActive)         // First filter
    .Where(i => i.Price > 100)      // Second filter
    .Select(i => i.Name);            // Final transformation

// WORST: Select -> Where -> Where
var result = items
    .Select(i => new { i.Name, i.Price, i.IsActive })
    .Where(i => i.IsActive)
    .Where(i => i.Price > 100);