Always will be ready notify the world about expectations as easy as possible: job change page
Jan 7

6 common LINQ mistakes you might be doing



Few days ago I stopped myself while writing code. I wrote my LINQ filtering wrong.

items.Where(x => x > 0).Any();

(Obviously, it’s a pseudo code)

I realized my mistake immediately, changed the code, and went on with my day.

Then it started bugging me. What other LINQ methods could I have misused in the similar way? Not noticing the mistake and thinking I picked the best solution for the problem I was facing?

I started digging around in documentation, in my and others’ code bases, and here are some common LINQ mistakes that I have found.

1. Single() vs First()

// Incorrect
var vehicle1 = vehicles.Single(x => x.Id == 42);
var vehicle2 = vehicles.SingleOrDefault(x => x.Id == 42);

// Correct
var vehicle1 = vehicles.First(x => x.Id == 42);
var vehicle2 = vehicles.FirstOrDefault(x => x.Id == 42);

Why? What’s the difference?

  • Incorrect: Single() or SingleOrDefault() makes sure that there is just one and only one match in the set of vehicles — there are no two or more vehicles with Id 42.
  • Correct: First() or FirstOrDefault() returns the first match — first vehicle with Id 42.

In most cases you are not ensuring that there is just one match. Often, that shouldn’t be the case — your primary key (Id) should be unique.

In terms of SQL it would look like this:

  • Single() or SingleOrDefault()SELECT 2 …
  • First() or FirstOrDefault()SELECT 1 …

You can already see where this is going — the first one should have worse performance.

What about benchmarks (which you can run yourself here)?

Sample size of 10,000
Sample size of 10,000

Now we have some proof — use First() or FirstOrDefault(). Grab the Single() and SingleOrDefault() only when you really need it.

2. Where().First()

// Incorrect
var vehicle1 = vehicles
  .Where(x => x.Brand == "Porsche")
var vehicle2 = vehicles
  .Where(x => x.Brand == "Porsche")

// Correct
var vehicle1 = vehicles.First(x => x.Brand == "Porsche");
var vehicle2 = vehicles.FirstOrDefault(x => x.Brand == "Porsche");

What’s the difference this time?

  • Incorrect: First, get all the vehicles with the brand that equals to “Porsche”. Then retrieve the first of those vehicles.
  • Correct: Get the first vehicle with the brand that equals to “Porsche” — then stop there.

Benchmark time? Benchmark time.

Sample size of 10,000
Sample size of 10,000

There is a small difference which proves the point — First() or FirstOrDefault() does the same as Where().First() — but with better performance.

3. Where().Where()

// Incorrect
var porscheVehicles = vehicles
  .Where(x => x.Brand == "Porsche")
  .Where(x => x.ProductionYear > 2010);

// Correct
var porscheVehicles = vehicles
  .Where(x => x.Brand == "Porsche" && x.ProductionYear > 2010);


  • Incorrect: Retrieve all the vehicles with brand Porsche, and out of them take vehicles with production year greater than 2010.
  • Correct: Retrieve all vehicles with brand Porsche with production year greater than 2010.

In SQL it could end up like SELECT * FROM (SELECT FROM …).

And here we go — another benchmark.

Sample size 10,000
Sample size 10,000

Contrary to most benchmarks where just numbers are used — this time it’s a benchmark that is similar to the example shown above — using vehicle objects. As a result, more memory is allocated. Code can be seen here.

As you can see, we have another proof — using just one Where is much more efficient.

4. OrderBy().OrderBy()

// Incorrect
var orderedVehicles = vehicles
  .OrderBy(x => x.Brand)
  .OrderBy(x => x.ProductionYear);

// Correct
var orderedVehicles = vehicles
  .OrderBy(x => x.Brand)
  .ThenBy(x => x.ProductionYear);

This is not a performance issue but instead a logical issue. What exactly is happening in the example above?

  • Incorrect: Sort vehicles by brand. Then ignore the previous sort and re-sort the vehicles by production year.
  • Correct: Sort vehicles by brand. Then take the previous sort into account and then also sort them by production year.

Note that the same applies to OrderByDescending() and ThenByDescending().

5. Empty Count()

// Incorrect
var count1 = vehiclesList.Count();
var count2 = vehiclesArray.Count();

// Correct
var count1 = vehiclesList.Count;
var count2 = vehiclesArray.Length;

What’s the problem here?

We shouldn’t be using Enumerable.Count() for arrays and any collections that implement ICollection<T> or ICollection interface — these include List<T> and Dictionary<T>.

We should be instead using Count property for ICollection implementation and Length for arrays.

Although, when we look into the LINQ source code we can see the following:

public static int Count<TSource>(this IEnumerable<TSource> source)
    if (source == null)
        throw Error.ArgumentNull("source");
    ICollection<TSource> collectionoft = source as ICollection<TSource>;
    if (collectionoft != null)
        return collectionoft.Count;
    ICollection collection = source as ICollection;
    if (collection != null)
        return collection.Count;
    int count = 0;
    using (IEnumerator<TSource> e = source.GetEnumerator())
            while (e.MoveNext()) count++;

    return count;

When it can, it will early return Count instead of doing O(n) operation.

6. Count() instead of Any() or All()

// Incorrect
bool any1 = vehicles.Count() > 0;
bool any2 = vehicles.Count(x => x.Brand = "Porsche") > 0;
bool all = vehicles.Count(x => x.Brand = "Porsche") == vehicles.Count();

// Correct
bool any1 = vehicles.Any();
bool any2 = vehicles.Any(x => x.Brand = "Porsche");
bool all = vehicles.All(x => x.Brand = "Porsche");

Well, first of all I am curious if you noticed I used Count() instead of Count. Props to you if you did — that could be the first incorrect point.
(Although, from the small code snippet, it’s not obvious if it’s List<T> or not)


  • Incorrect: First do a full iteration of the (matching) vehicles. Then compare the amount.
  • Correct: Check if there is any vehicle that matches the condition — then stop. In case of All — stop when vehicle doesn’t match the condition.

When it comes to All there are other problems that we won’t get into now.

What about performance?

Sample size of 10,000
Sample size of 10,000

As you can see, operations with Count() are much slower.

Note that Count() compared to Any() is about the same — that’s because List<T> was used — Count() returns Count property.

When it comes to Any() and All() we managed to cut a lot of time. Note that, in the worst-case scenario these operations are O(n) as well and might take the same amount of time as using Count(). We should still rather use Any() and All() in hopes of making our code perform better.

Final words

While most LINQ providers optimize in most of the cases, it’s important to know about these limitations and differences. It’s important to know which LINQ method to use and when as it makes our code more readable and performs better.

I knew about most of these mistakes (That didn’t stop me from making them again and again). Did you? Do you know any other LINQ mistakes that people make often? Share them with us.

Remember, you can run all of the benchmarks yourself here.

May 12
Author: ByteHide
Index In C# async-await, what is the main difference between How does the In C# async-await, how can deadlocks occur, and what are some effective techniques to avoid them in your...
Jan 13, 2023
Author: Jaydeep Patil
We are going to discuss the Unit of Work design pattern with the help of a generic repository and step-by-step implementation using .NET Core 6 Web API.Agenda Repository Pattern Unit of Work ...
Jul 24, 2023
Author: Mihai Sandu
Small changes, Big wins: How little tweaks make your code easy on the eyeWhen we think of clean code, our brain jumps to SOLID principles, short classes, no comments, and good design patterns. While all of those apply, they are...
Dec 1, 2023
Author: MESCIUS inc.
Reporting is a common task in business applications, and for that, ComponentOne includes a specialized FlexReport library that allows you to make complex reports. But sometimes, using specialized tools can be too tricky or not flexible enough.For example, if you...
Написать сообщение

© 1999–2024 WebDynamics
1980–... Sergey Drozdov
Area of interests: .NET Framework | .NET Core | C# | ASP.NET | Windows Forms | WPF | HTML5 | CSS3 | jQuery | AJAX | Angular | React | MS SQL Server | Transact-SQL | ADO.NET | Entity Framework | IIS | OOP | OOA | OOD | WCF | WPF | MSMQ | MVC | MVP | MVVM | Design Patterns | Enterprise Architecture | Scrum | Kanban