Most Common Mistakes Developers Make in LINQ (and How to Avoid Them)

Language Integrated Query (LINQ) is one of the most elegant and powerful features in C#. It allows you to query collections, databases, XML, and more with concise, readable syntax.

But as many developers quickly learn — just because LINQ looks simple doesn’t mean it’s foolproof.
Subtle mistakes can cause performance issues, unexpected results, or even runtime exceptions.

In this post, we’ll explore some of the most common mistakes developers make when using LINQ — and how to fix them with clean, efficient code.


1. Forgetting Deferred Execution

Deferred execution means that a LINQ query isn’t executed until you actually iterate over it (for example, using foreach or calling .ToList()).

Mistake Example:

var numbers = new List<int> { 1, 2, 3 };
var query = numbers.Select(n => n * 2);

numbers.Add(4);

foreach (var n in query)
{
    Console.WriteLine(n);
}

Output:

2, 4, 6, 8

Surprised? The Select query wasn’t executed when defined — it was executed later, after you added 4.

Fix:
If you need to lock in the results immediately, force immediate execution:

var result = numbers.Select(n => n * 2).ToList();

2. Using ToList() Too Early (or Too Often)

While .ToList() forces execution, many developers overuse it, creating unnecessary lists in memory.

Bad Example:

var data = db.Users.ToList()
                  .Where(u => u.IsActive)
                  .Select(u => u.Name);

Here, .ToList() pulls all users from the database before filtering — terrible for performance.

Fix:
Only call .ToList() after all filtering and projections are done:

var data = db.Users
             .Where(u => u.IsActive)
             .Select(u => u.Name)
             .ToList();

3. Forgetting That LINQ Queries Are Immutable

LINQ queries don’t modify the original collection — they return a new sequence.

Mistake Example:

var numbers = new List<int> { 1, 2, 3 };
numbers.Where(n => n > 1);
Console.WriteLine(string.Join(",", numbers)); // 1,2,3

The Where() filter didn’t change the list.

Fix:
Assign the result to a new variable:

var filtered = numbers.Where(n => n > 1).ToList();

4. Confusing First() vs FirstOrDefault()

These two look similar but behave very differently when there’s no matching element.

Example:

var user = users.First(u => u.Id == 10); // Throws InvalidOperationException if not found

Fix:
Use FirstOrDefault() to safely handle missing results:

var user = users.FirstOrDefault(u => u.Id == 10);
if (user != null)
{
    Console.WriteLine(user.Name);
}

5. Not Using Any() Instead of Count()

A very common LINQ mistake is checking if a collection has items using Count().

Inefficient Example:

if (users.Count() > 0)
{
    // ...
}

This counts all records in the collection — even if you only need to know whether one exists.

Fix:
Use Any():

if (users.Any())
{
    // ...
}

It stops as soon as it finds one match — much faster and cleaner.


6. Misusing Select When You Need SelectMany

Select() transforms each element into a single result.
SelectMany() flattens nested collections.

Mistake Example:

var allOrders = customers.Select(c => c.Orders);

Here, allOrders becomes a collection of collections (IEnumerable<List<Order>>).

Fix:
Flatten with SelectMany():

var allOrders = customers.SelectMany(c => c.Orders);

7. Forgetting That LINQ to Entities Is Not LINQ to Objects

Some operations work fine in LINQ to Objects but not in LINQ to Entities (EF).

Example:

var users = db.Users.Where(u => SomeCSharpMethod(u.Name)).ToList();

This will throw a runtime error because Entity Framework can’t translate SomeCSharpMethod into SQL.

Fix:
Do filtering that depends on .NET methods after the data is loaded:

var users = db.Users.ToList()
                    .Where(u => SomeCSharpMethod(u.Name));

8. Assuming Distinct() Works Automatically for Complex Types

By default, Distinct() compares objects by reference, not by value.

Example:

var customers = new List<Customer>
{
    new Customer { Id = 1, Name = "John" },
    new Customer { Id = 1, Name = "John" }
};
var unique = customers.Distinct(); // Still contains duplicates

Fix:
Provide a custom IEqualityComparer or use anonymous projection:

var unique = customers
    .Select(c => new { c.Id, c.Name })
    .Distinct();

9. Forgetting to Dispose Database Contexts

When using LINQ to Entities or LINQ to SQL, not disposing of your context can cause memory leaks or open connections.

Mistake Example:

var users = new MyDbContext().Users.ToList(); // Context never disposed

Fix:
Use a using block:

using (var db = new MyDbContext())
{
    var users = db.Users.ToList();
}

10. Ignoring Performance of Chained Queries

LINQ queries look elegant but can chain a lot of operations, especially with Select(), Where(), and OrderBy().

Each operation creates a new enumerable, adding overhead if used carelessly.

Fix:

  • Combine filters where possible.
  • Cache expensive results.
  • Benchmark large datasets using profiling tools.
Home » Most Common Mistakes Developers Make in LINQ (and How to Avoid Them)