Just created a simple benchmark, based on your sample, and added one more method with filtering using Where(book => book.Price < 30)
and count (which should be the fastest one)
[SimpleJob]
public class LinqBenchmark
{
private IEnumerable<Book> Books;
[GlobalSetup]
public void Setup()
{
Books = new List<Book>()
{
new Book { Price = 20 },
new Book { Price = 30 },
new Book { Price = 40 },
new Book { Price = 50 },
new Book { Price = 60 },
new Book { Price = 70 },
new Book { Price = 80 },
new Book { Price = 10 }
};
}
[Benchmark]
public int SelectWhereCount()
{
return Books.Select(book => book.Price).Where(book => book < 30).Count();
}
[Benchmark]
public int SelectCount()
{
return Books.Select(book => book.Price).Count(book => book < 30);
}
[Benchmark]
public int WhereCount()
{
return Books.Where(book => book.Price < 30).Count();
}
[Benchmark]
public int Count()
{
return Books.Count(book => book.Price < 30);
}
internal class Book
{
public int Price { get; internal set; }
}
}
Count
method with predicate works faster then other ones

You can refer to implementation details to see and understand a performance difference. Count(book => book.Price < 30)
pass each element in a loop to Func<TSource, bool> predicate
and increments count, if gets true
.
Where
and Select
under the hood use special WhereSelectEnumerableIterator
or WhereListIterator
class and then calculate the count. The reason why Where
and Count
works faster is perfectly explained in LINQ performance Count vs Where and Count thread, leave it here for the reference.
So, in terms of performance Books.Where(book => book.Price < 30).Count()
is fastest option, in terms of readability two last options look more convenient, IMO.