In this article, we are going to learn the main differences between Any and Count methods from LINQ.
We work with different collections in C# all the time, and we often need to check if there are any records inside the collection or if it is empty. Both methods can help us to achieve that. We are going to see how each method works internally and compare the efficiency of each approach to determine which one we should use in specific use cases.
To download the source code for this article, you can visit our GitHub repository.
Let’s dive into it.
What are Any() and Count() Methods Used For?
BothAny()
andCount()
methods are part of the LINQ (Language Integrated Query), which is a uniform query language introduced with .NET 3.5.
The main purpose of LINQ is to retrieve data from different data sources, while Any()
andCount()
are one of the most popular LINQ methods we use in our everyday coding with C#.
How Does Any() Method Work?
We use the Any()
method to determine if at least one element is present in the data source. If the data source is not empty, the method will return true
. Otherwise, it will return false
.
There are two different overloads of theAny()
method that we can use to check if a data source contains data or not:
public static bool Any<TSource> (this IEnumerable<TSource> source);
This is the extension method that doesn’t accept any additional parameters.
We can use the second overload of the method to determine if there are any records in the collection that satisfy the given condition:
public static bool Any<TSource> (this IEnumerable<TSource> source, Func<TSource,bool> predicate);
In this case, we can provide a Func<TSource,bool>
predicate as a parameter to specify the condition we want to check.
How Does Count() Method Work?
On the other hand, we use the Count()
extension method to count the number of records in the collection. Similar to theAny()
method, theCount()
method has two different overloads.
The first overload is the parameterless method which will return the number of elements present in the collection:
public static int Count<TSource> (this IEnumerable<TSource> source);
We can use the other method with the Func<TSource,bool>
predicate to specify the condition. This method will return a number based on the elements in the collection that satisfy a condition:
public static int Count<TSource> (this IEnumerable<TSource> source, Func<TSource,bool> predicate);
Prepare the Environment
Now, let’s prepare our environment for comparison between the two methods.
First, let’s create a new class that we will use to perform different operations withAny()
andCount()
methods:
[Orderer(SummaryOrderPolicy.FastestToSlowest)]public class PerformanceBenchmark
Here we create thePerformanceBenchmark
class with theOrderer
annotation added to order the results from fastest to slowest.
Then, let’s add our collection to the class and initialize it with the Range()
static method from Enumerable
:
private static readonly IEnumerable<int> _numbersEnumerable = Enumerable.Range(1, 1000);
Here we populate the data with numbers from 1 to 1000.
We will use the_numbersEnumerable
member to perform different operations withAny()
andCount()
methods.
Any() without Condition
Next, let’s create our first benchmark method inside the PerformanceBenchmark
class:
[Benchmark]public bool CheckWithAny(){ return _numbersEnumerable.Any();}
In this simple method, we return thebool
type, based on the_numbersEnumerable
value. Here we use theAny()
method without parameters, so it will returntrue
if there are any records in theIEnumerable
. We use theBenchmark
annotation from the BenchmarkDotNet library to mark the method for benchmark comparison.
Any() with Condition
Let’s now check how we can implement theAny()
method by passing the predicate into the method:
[Benchmark]public bool CheckWithAnyAndCondition(){ return _numbersEnumerable.Any(num => num > 500);}
In theCheckWithAnyAndCondition()
method, we check if we have any values in the _numberEnumerable
that are greater than 500. If that is the case, the method will returntrue
. Otherwise, it will return false
.
Count() without Condition
Now, let’s look at the Count()
method without parameters. This method returns an int
value based on the number of elements in the collection. To perform the same logic as with the Any()
method, we need to check if the return value of theCount()
method is greater than zero:
[Benchmark]public bool CheckWithCount(){ return _numbersEnumerable.Count() > 0;}
Here we implement theCheckWithCount()
method that returns thebool
value. The method will returntrue
if there are any elements in the_numbersEnumerable
. Otherwise, it will return false
.
Count() with Condition
With that, let’s now use the Count()
method with the parameter:
[Benchmark]public bool CheckWithCountAndCondition(){ return _numbersEnumerable.Count(num => num > 500) > 0;}
Same as on the previousAny()
example, here we returntrue
if there are any elements in the _numbersEnumerable
greater than 500.
Any vs Count Benchmark
With all of our methods ready, we’re going to perform a benchmark with the BenchmarkDotNet library to measure the time performance for each approach.
For that, let’s modify ourProgram
class:
BenchmarkRunner.Run<PerformanceBenchmark>();
Here we execute theRun
method that will perform the comparison on all methods from our PerformanceBenchmark
class.
Benchmark Comparison with 1000 Records
Finally, let’s run our console application in the release configuration with thedotnet run -c Release
command and get the results:
| Method | Mean | Error | StdDev ||--------------------------- |------------:|-----------:|-----------:|| CheckWithAny | 10.38 ns | 0.209 ns | 0.196 ns || CheckWithCount | 11.66 ns | 0.255 ns | 0.340 ns || CheckWithAnyAndCondition | 2,734.07 ns | 52.861 ns | 70.568 ns || CheckWithCountAndCondition | 5,505.87 ns | 108.016 ns | 120.059 ns |
Here we can see our benchmark results based on theIEnumerable
with 1000 records.
Both Any()
andCount()
methods are faster without the condition. Without the condition, both methods are pretty close, with theAny()
method being slightly faster. On the other hand, we can see that theAny()
method with the condition performs much better as it takes 2,734 ns, while the Count()
method with the condition takes 5,505 ns.
Benchmark Comparison with 50,000 Records
We should always check the performance of the methods with different sizes, so let’s change the size ofIEnumerable
:
private static readonly IEnumerable<int> _numbersEnumerable = Enumerable.Range(1, 50000);
Now, let’s run our program again and see how methods perform with 50,000 records:
| Method | Mean | Error | StdDev ||--------------------------- |--------------:|-------------:|-------------:|| CheckWithAny | 10.77 ns | 0.214 ns | 0.200 ns || CheckWithCount | 11.83 ns | 0.210 ns | 0.196 ns || CheckWithAnyAndCondition | 2,839.01 ns | 56.751 ns | 75.761 ns || CheckWithCountAndCondition | 292,231.08 ns | 5,135.502 ns | 7,527.553 ns |
Again, we see similar results. BothAny()
andCount()
methods perform similarly when working without the condition. On the other hand, we can see that theAny()
method performs multiple times faster when checking through the 50,000 records with the specified condition.
That said, if we want to check if there are any records in the IEnumerable
type, we should go with the Any()
method.
Count Property
In some cases, when ourIEnumerable
is actually anICollection
like List
for example, we can use the Count
property:
public int Count { get; }
This is different from theCount()
extension method that works on any IEnumerable
and iterates through each element to determine how many elements are there.
On the other hand, theCount
property uses the_size
private variable inside the ICollection
type which is maintained byAdd()
orRemove()
methods to increase/decrease the value based on the operation. That means that this operation is O(1) or instant, while theCount()
method needs to iterate through all elements – O(n).
We should note that the LINQ code has underlying optimizations to detect if there is aCount
property. One limitation of theCount
property is that we cannot use it with the condition.
If we work with arrays, we can use the Length
property in the same way.
Count Property Benchmark
Let’s add another private field to ourPerformanceBenchmark
class:
private static readonly ICollection<int> _numbersList = Enumerable.Range(1, 50000).ToList();
Here we add the_numbersList
field with theRange()
method. The only difference from our_numbersEnumerable
is that we call theToList()
method to convert the data to the List
type,which will have access to the Count
property.
Then, let’s add a new method to check if there are any records in the list with theCount
property:
[Benchmark]public bool CheckWithCountProperty(){ return _numbersList.Count > 0;}
Finally, let’s run our benchmark again with 50,000 records and check the results:
| Method | Mean | Error | StdDev ||--------------------------- |----------------:|--------------:|--------------:|| CheckWithCountProperty | 0.2891 ns | 0.0359 ns | 0.0657 ns || CheckWithAny | 10.7252 ns | 0.2266 ns | 0.2225 ns || CheckWithCount | 11.8063 ns | 0.2618 ns | 0.4152 ns || CheckWithAnyAndCondition | 2,813.2671 ns | 54.9630 ns | 61.0913 ns || CheckWithCountAndCondition | 287,027.1517 ns | 4,533.0244 ns | 4,240.1939 ns |
Awesome, here we can see that theCheckWithCountProperty()
method executes almost instantly.
Conclusion
In this article, we’ve learned a lot about the differences between Any()
andCount()
methods from LINQ. We also had a look at theCount
property that we can use on all ICollection
types in C#. With different methods and conditions, we got different performance results.
The main conclusion is that we should always use theCount
property when possible and when we don’t need to perform any additional conditions. Otherwise, when we use the types fromIEnumerable
that don’t have theCount
property or we want to use conditions, we should go with theAny()
method.
TheAny()
method will enumerate over a single item, while theCount()
method causes complete enumeration. Another good reason to useAny()
most of the time is to clarify the intent of the developer since the name of the method says what we want to check.
With that, this is a simpler and cleaner option to optimize our C# code.