Performance of LINQ Any vs FirstOrDefault != null
You are mixing things here. You are talking about collections, but you don't seem to use LINQ to objects but you are querying a database.
LINQ to objects:Enumerable.Any
and Enumerable.FirstOrDefault
should perform the same, because their code is near identical:
FirstOrDefault
:
foreach (TSource source1 in source)
{
if (predicate(source1))
return source1;
}
return default (TSource);
Any
:
foreach (TSource source1 in source)
{
if (predicate(source1))
return true
}
return false;
LINQ to some database:
You are using Entity Framework, LINQ to SQL or NHibernate and use Queryable.Any
and Queryable.FirstOrDefault
on the corresponding data context.
In this case, there are really no collections, because these calls are not executed on in memory objects but translated to SQL.
This means, the performance difference stems from how the LINQ provider translates the code to SQL, so the best would be to first check the statements created. Are they equivalent? Or are they very different (select count(0) from X
vs. select top 1 from X
)? Then the difference might lie in the query optimizer of the DB, indexes and what not...
The enumeration in Any()
stops as soon as it finds a matching item as well:
https://docs.microsoft.com/en-us/dotnet/api/system.linq.enumerable.any
I would expect the performance to be very similar. Note that the FirstOrDefault
version won't work with a collection of value types (since the default isn't null) but the Any
version would.
The problem with this question is that it is not asked within context. I am providing an answer because I see this a lot in code reviews and it bothers me. LINQ should not be an excuse to stop thinking.
var people = new [] { "Steve", "Joe" };
if (people.Any(s => s == "Joe"))
{
var joe = people.First(s => s == "Joe");
// do something with joe
}
// if people is 1,000,000 people and joe is near the end do we want BigO to approach 2N here at worst case ?
var joe1N = people.FirstOrDefault(s => s == "Joe");
if (joe1N != null)
{
// do something with joe
}
// or do we want to ensure worst case is N by simply using a variable ?
Why should any continue after it has found an element satisfying the condition? If the condition applies to 1 element, that qualifies as "any".
I think they should both perform about the same, but Any() does express your intention more clearly.