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.
Let’s dive into it.
What are Any() and Count() Methods Used For?
Both Any()
and Count()
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()
and Count()
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 the Any()
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 the Any()
method, the Count()
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 with Any()
and Count()
methods:
[Orderer(SummaryOrderPolicy.FastestToSlowest)] public class PerformanceBenchmark
Here we create the PerformanceBenchmark
class with the Orderer
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 with Any()
and Count()
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 the bool
type, based on the _numbersEnumerable
value. Here we use the Any()
method without parameters, so it will return true
if there are any records in the IEnumerable
. We use the Benchmark
annotation from the BenchmarkDotNet library to mark the method for benchmark comparison.
Any() with Condition
Let’s now check how we can implement the Any()
method by passing the predicate into the method:
[Benchmark] public bool CheckWithAnyAndCondition() { return _numbersEnumerable.Any(num => num > 500); }
In the CheckWithAnyAndCondition()
method, we check if we have any values in the _numberEnumerable
that are greater than 500. If that is the case, the method will return true
. 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 the Count()
method is greater than zero:
[Benchmark] public bool CheckWithCount() { return _numbersEnumerable.Count() > 0; }
Here we implement the CheckWithCount()
method that returns the bool
value. The method will return true
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 previous Any()
example, here we return true
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 our Program
class:
BenchmarkRunner.Run<PerformanceBenchmark>();
Here we execute the Run
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 the dotnet 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 the IEnumerable
with 1000 records.
Both Any()
and Count()
methods are faster without the condition. Without the condition, both methods are pretty close, with the Any()
method being slightly faster. On the other hand, we can see that the Any()
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 of IEnumerable
:
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. Both Any()
and Count()
methods perform similarly when working without the condition. On the other hand, we can see that the Any()
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 our IEnumerable
is actually an ICollection
like List
for example, we can use the Count
property:
public int Count { get; }
This is different from the Count()
extension method that works on any IEnumerable
and iterates through each element to determine how many elements are there.
On the other hand, the Count
property uses the _size
private variable inside the ICollection
type which is maintained by Add()
or Remove()
methods to increase/decrease the value based on the operation. That means that this operation is O(1) or instant, while the Count()
method needs to iterate through all elements – O(n).
We should note that the LINQ code has underlying optimizations to detect if there is a Count
property. One limitation of the Count
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 our PerformanceBenchmark
class:
private static readonly ICollection<int> _numbersList = Enumerable.Range(1, 50000).ToList();
Here we add the _numbersList
field with the Range()
method. The only difference from our _numbersEnumerable
is that we call the ToList()
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 the Count
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 the CheckWithCountProperty()
method executes almost instantly.
Conclusion
In this article, we’ve learned a lot about the differences between Any()
and Count()
methods from LINQ. We also had a look at the Count
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 the Count
property when possible and when we don’t need to perform any additional conditions. Otherwise, when we use the types from IEnumerable
that don’t have the Count
property or we want to use conditions, we should go with the Any()
method.
The Any()
method will enumerate over a single item, while the Count()
method causes complete enumeration. Another good reason to use Any()
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.