Reputation: 42175
Which is more efficient - to attempt to iterate an empty list, or to test if there are any items in the list before attempting to iterate?
For example, first get an empty list of things:
var listOfThings = GetZeroThings(); // this returns 0 things
is it less efficient to attempt to execute this:
foreach (var thing in listOfThings)
{
}
or should I test whether there are any items? e.g.
if (listOfThings.Any())
{
foreach (var thing in listOfThings)
{
}
}
Upvotes: 0
Views: 71
Reputation: 30813
My simple test shows that the one with Any
is slower:
[2016-04-18 03:01:55.900 UTC] Without Any: 254 ms
[2016-04-18 03:01:56.266 UTC] With Any: 363 ms
The code is below (may not be reproducable since you do not have my component logBox
, but is included to show the fairness of the test):
IEnumerable<int> listOfThings = new List<int>();
logBox.GetTimeLapse();
for (int i = 0; i < 10000000; ++i)
foreach (var thing in listOfThings)
Console.WriteLine("Do something!");
logBox.WriteTimedLogLine("Without Any: " + logBox.GetTimeLapse());
logBox.GetTimeLapse();
for (int i = 0; i < 10000000; ++i)
if (listOfThings.Any())
foreach (var thing in listOfThings)
Console.WriteLine("Do something!");
logBox.WriteTimedLogLine("With Any: " + logBox.GetTimeLapse());
Which I think is making sense because of the present of extra Any
while your foreach (var thing in listOfThings)
alone would have already done the checking for you anyway.
Edit:
Additional note by Jonathan Allen which I think is worth included: The line if (listOfThings.Any())
(1) allocates memory and (2) makes a virtual dispatch call. The line foreach (var thing in listOfThings)
does neither.
Upvotes: 2
Reputation: 101680
If you look at Any's source:
public static bool Any<TSource>(this IEnumerable<TSource> source)
{
if (source == null) throw Error.ArgumentNull("source");
using (IEnumerator<TSource> e = source.GetEnumerator()) {
if (e.MoveNext()) return true;
}
return false;
}
You can see that all it's doing is to call GetEnumerator
on the source collection and call MoveNext
method. The foreach
will do exactly the same for an empty collection so, calling Any
before foreach
is redundant. But I believe it won't make any significant affect in terms of performance and I think using Any
before foreach
makes the code more readable.
Upvotes: 5
Reputation: 27357
You need to profile it. It's really impossible to give you an answer. That being said, checking Any()
looks like it can cause issues.
For example:
void Main()
{
var listOfThings = GetThings();
if (listOfThings.Any())
{
foreach (var item in listOfThings)
{
Console.WriteLine("A");
}
}
}
public IEnumerable<int> GetThings()
{
Thread.Sleep(10000);
yield return 1;
}
Assuming the first element is expensive to get, you're doing the work twice. It entirely depends on how your collection behaves. As above, you need to profile your own circumstances.
Just by looking at it, it seems like Any()
will always be redundant, as it grabs the enumerator anyway.
Upvotes: 1