Updated on

To check whether a collection has anything in it, use Any(). It stops at the first element; Count() may walk the whole sequence to produce a number we then throw away.

The exception is a List<T>, an array, or anything else with a Count or Length property. Those already know their size, so list.Count > 0 reads it directly, and that is why some analyzers flag Any() on a List<T>.

To download the source code for this article, you can visit our GitHub repository.

What Are Any() and Count() in C#?

Any() and Count() are LINQ extension methods on IEnumerable<T>. Any() answers whether the sequence has at least one element and returns a bool; Count() answers how many and returns an int.

Both take an optional predicate. Any(x => x.IsActive) asks whether any element matches; Count(x => x.IsActive) asks how many do.

The difference that matters is how far each one has to go before it can answer. Any() stops as soon as it knows: the first element on a sequence, the stored size on a collection that has one. Count() has no such shortcut on an arbitrary sequence: it walks every element to reach a total, and then we compare that total to zero and discard it.

That gap is invisible on a list of ten items and enormous on a filtered query running against a database, which is why the choice is worth making deliberately rather than by habit.

Both methods belong to LINQ, and both come in the same two shapes, so let’s look at each one in turn.

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. If we are choosing between this and the array-specific method of the same shape, we cover how Any() compares with Exists() separately.

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.

Is this material useful to you? Consider subscribing and get ASP.NET Core Web API Best Practices eBook for FREE!

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. The predicate here plays the same role it plays in the Where() method, except that we never materialize the filtered sequence.

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. If we want the wider picture beyond these two methods, we also measure LINQ performance in .NET across the common operators.

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 |

These 1000-element figures were measured on .NET 6, which is the framework the sample originally shipped on; every table below this one is a fresh .NET 10 run. The ordering is the point rather than the absolute numbers, and the ordering has held across releases even though the absolute cost of LINQ has fallen a long way — see what changed in recent LINQ releases.

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 on .NET 10 and see how methods perform with 50,000 records:

|                     Method |           Mean |       Error |      StdDev |         Median |
|--------------------------- |---------------:|------------:|------------:|---------------:|
|             CheckWithCount |      0.4802 ns |   0.0509 ns |   0.1476 ns |      0.4261 ns |
|               CheckWithAny |      0.9963 ns |   0.0917 ns |   0.2674 ns |      0.9528 ns |
|   CheckWithAnyAndCondition |    508.5902 ns |  13.3314 ns |  37.6015 ns |    496.4367 ns |
| CheckWithCountAndCondition | 52,931.2837 ns | 889.4798 ns | 913.4302 ns | 52,869.2627 ns |

The two rows without a condition both land in the sub-nanosecond range — a few CPU cycles each, over a sequence of 50,000 elements. That is not Any() winning a race against a walk; neither method walks anything here. Enumerable.Range() hands back a sequence that can report its own size: it implements ICollection<int>, and both Count() and Any() check for that interface before they touch an enumerator. So both calls read one stored number, which is why they land within a nanosecond of each other instead of 50,000 elements apart.

That is also why those two rows do not grow with the collection: reading a stored size costs the same whether it says 1000 or 50,000. It is the honest reading of a result that otherwise looks like a paradox — a supposedly O(n) count of 50,000 elements finishing in less time than a single cache miss.

The condition is where the two part company, and here the size does matter. Any() with a predicate stops at the first element greater than 500, so it never sees the other 49,000-odd. Count() with a predicate has to test every element to produce a total, and only then do we compare that total to zero.

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, which works on any IEnumerable and, when the source cannot report its own size, iterates through each element to determine how many there are.

On the other hand, concrete collections such as List<T> track their size in a field as we mutate them, incremented by Add() and decremented by Remove(), so the Count property just returns that field. That means that this operation is O(1) or instant, while a Count() call that has to enumerate is O(n). ICollection<T> itself is only the interface that promises such a property exists — it holds no state of its own, and we compare it with its neighbours in IEnumerable, ICollection, IList, and List.

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.

Is this material useful to you? Consider subscribing and get ASP.NET Core Web API Best Practices eBook for FREE!

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 |         Median |
|--------------------------- |---------------:|--------------:|--------------:|---------------:|
|     CheckWithCountProperty |      0.3510 ns |     0.0439 ns |     0.0555 ns |      0.3319 ns |
|             CheckWithCount |      0.4790 ns |     0.0491 ns |     0.1284 ns |      0.4857 ns |
|               CheckWithAny |      0.5256 ns |     0.0508 ns |     0.1442 ns |      0.4809 ns |
|   CheckWithAnyAndCondition |    476.0262 ns |     9.5807 ns |    11.4052 ns |    473.8749 ns |
| CheckWithCountAndCondition | 61,071.0765 ns | 3,426.3682 ns | 9,885.8556 ns | 56,536.1084 ns |

Here we can see that the CheckWithCountProperty() method executes almost instantly. It sits alongside the two size-reading rows above it rather than far below them, which is the same story told a third time: a property read, an ICollection<int> size read through Count(), and an ICollection<int> size read through Any() are all one field access.

Why Does My IDE Say to Compare Count to 0 Instead of Using Any()?

Because on a type that already stores its size, reading that value is the direct way to ask, and the analyzer would rather we asked directly.

The suggestion fires when the collection is a List<T>, an array, or another type with a Count, Length, or IsEmpty member. It is not telling us that Any() walks the collection: Enumerable.Any() checks for ICollection<T> first and reports whether that same stored count is non-zero, so on a List<T> both forms read the same number.

What the property saves is a type check and a call. CA1860’s own rationale is short: “It’s more efficient to rely on the collection’s own properties, and it also clarifies intent.”

The advice does not generalise. On an IEnumerable<T> with no stored size (a LINQ query, a database query, a generator) there is no property to read, and producing a count means running the whole sequence, so Any() is the one that stops early.

The exact wording most developers paste into a search box — prefer comparing ‘Count’ to 0 rather than using ‘Any()’, both for clarity and for performance — is ReSharper and Rider’s, not the text of any Microsoft rule.

The .NET analyzer analogue is CA1860, “Avoid using ‘Enumerable.Any()’ extension method”, category Performance, enabled by default in .NET 10 as a suggestion, and it fires when Any() is called on a type that has a Length, Count, or IsEmpty property. Two neighbouring rules point the other way: CA1827 (“Do not use Count/LongCount when Any can be used”) and CA1829 (“Use Length/Count property instead of Enumerable.Count method”). Read from Microsoft Learn on 9 August 2026.

Read together, the three rules are consistent rather than contradictory. They all say the same thing: ask the cheapest question the type can answer. On a List<T> that is the property, on a sequence it is Any(), and it is never Count() > 0.

Any() vs Count() in C#: Which One Should We Use?

Use Any() on anything we only have as a sequence, and the Count or Length member on anything that has one.

The benchmark above shows why. With a predicate over 50,000 items, Any() finishes in under half a microsecond and Count() takes about sixty: more than a hundredfold gap, because Any() stops at the first match and Count() cannot stop at all.

Without a predicate the two look identical, which is a result worth reading carefully rather than generalising: it is telling us the source already knew its size, not that Count() is cheap.

Intent is the other half of the argument. if (orders.Any()) says what we are asking. if (orders.Count() > 0) says we computed a total and then compared it to zero, which is not what we meant and not what the reader will assume we meant.

Bar chart comparing Any and Count execution time over 50,000 elements, with and without a predicate, highlighting that Count without a predicate uses a size fast path.

What we haveTo test "is it empty?"Why
List<T>, array, Dictionary<K,V>Count > 0 / Length > 0The size is stored; reading it is O(1)
IEnumerable<T> from LINQAny()Stops at the first element
IEnumerable<T> from LINQ, with a predicateAny(predicate)Stops at the first match
IQueryable<T> (EF Core)Any()Translates to EXISTS, not COUNT(*)
A sequence we also need the size ofCount(), once, into a variableEnumerating twice does the work twice
stringLength > 0 or string.IsNullOrEmpty()Neither LINQ method applies

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.

When the source cannot report its own size, the Any() method stops at the first element it needs, 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.

Tested with .NET 10.0.10.