Back to Blog
C#

C# LINQ Any: Usage and Behavior

Learn how to use the LINQ Any method in C#, including its syntax, predicate behavior, performance tradeoffs, and how it differs from Count() and Exists().

LINQC#IEnumerableLazy EvaluationCollection Methods
Illustration of the C# LINQ Any method checking whether a collection contains at least one matching element using a magnifying glass over abstract shapes.

The C# LINQ Any method answers a simple question: does a collection contain at least one element? When called without arguments, it returns true if the sequence has any elements at all. When called with a predicate, it returns true if at least one element satisfies that condition.

var numbers = new List<int> { 1, 2, 3, 4, 5 }; bool hasElements = numbers.Any(); // true bool hasEven = numbers.Any(n => n % 2 == 0); // true

The method is available as an extension method for IEnumerable<T>, which means it works with arrays, List<T>, HashSet<T>, Dictionary<TKey, TValue> (via KeyValuePair enumeration), and any custom type that implements the interface. It is also available on IQueryable<T> through the Queryable class, which changes how it behaves with database-backed collections.

The key behavioral trait of Any() is short-circuiting. When a predicate is supplied, the method iterates the sequence until it finds the first matching element and then stops. It does not enumerate the entire collection unless no element matches. This is the primary reason Any() is often preferred over approaches that count all elements first.

Basic Syntax and Return Behavior

Any() has two overloads. The parameterless version checks whether the sequence is non-empty. The predicate version checks whether any element satisfies the condition.

public static bool Any<TSource>(this IEnumerable<TSource> source); public static bool Any<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);

Both overloads return bool. The parameterless overload throws ArgumentNullException if source is null. The predicate overload throws the same exception if either source or predicate is null.

List<string> names = new List<string> { "Alice", "Bob", "Carol" }; bool anyNames = names.Any(); // true bool anyLongName = names.Any(n => n.Length > 4); // true bool anyShortName = names.Any(n => n.Length < 3); // false

For in-memory IEnumerable<T> sources, the predicate is evaluated once per element until a match is found or the sequence is exhausted. The order of elements in the source sequence can therefore affect how quickly Any() returns: if the first element satisfies the predicate, the method returns after a single iteration step.

Using Any() with a Predicate

The predicate overload is where Any() becomes genuinely useful. It replaces manual loops that would otherwise check for the existence of a matching element.

var orders = new List<Order> { new Order { Id = 1, Status = "Pending" }, new Order { Id = 2, Status = "Shipped" }, new Order { Id = 3, Status = "Delivered" } }; bool hasPendingOrders = orders.Any(o => o.Status == "Pending");

Compare this with the manual loop equivalent:

bool HasPendingOrders(List<Order> orders) { foreach (var order in orders) { if (order.Status == "Pending") { return true; } } return false; }

The Any() version is shorter and expresses the intent directly. It also works uniformly across any IEnumerable<T>, whereas a manual loop requires writing the same iteration logic for every collection type and condition.

A common alternative is Where(...).Any() instead of Any(predicate). In LINQ to Objects, Where(...).Any() also short-circuits and does not materialize a filtered list: it chains a filtering iterator with the existence check and stops at the first match. Any(predicate) performs the same check in a single call and avoids the extra iterator object, so it is the clearer expression of intent.

// Works, but adds an extra iterator layer bool result = orders.Where(o => o.Status == "Pending").Any(); // Same intent in one call bool result = orders.Any(o => o.Status == "Pending");

Any() vs Count() > 0: Why the Difference Matters

A common pattern in older code is collection.Count() > 0 to check whether a collection has elements. On many IEnumerable<T> sequences, especially lazy ones, the Count() LINQ method enumerates the entire sequence to count every element. Any() stops at the first element.

IEnumerable<int> collection = GetValues(); // May enumerate all elements bool hasItems = collection.Count() > 0; // Stops after the first element bool hasItems = collection.Any();

Count() has an optimization for types that implement ICollection<T> or ICollection: it reads the Count property directly instead of enumerating. That optimization can still apply when the runtime object is a List<T>, even if the variable is typed as IEnumerable<T>. For lazy sequences, however, there is no Count property to read, so Count() enumerates every element. If you only need to know whether any element exists, Any() avoids relying on that optimization.

The performance difference is most visible with lazy sequences, such as those produced by yield return, Select(), Where(), or File.ReadLines(). With an infinite sequence, Count() would never return, while Any() returns true immediately.

IEnumerable<int> InfiniteSequence() { int i = 0; while (true) { yield return i++; } } bool hasAny = InfiniteSequence().Any(); // true, returns immediately // InfiniteSequence().Count() would never complete

The same reasoning applies to the predicate overload. Any(predicate) stops at the first match. Count(predicate) > 0 must examine every element before returning.

Any() vs Exists() on List<T>

List<T> has its own Exists(Predicate<T>) method that predates LINQ. It behaves similarly to Any(predicate) but is only available on List<T> and arrays (as a static method on Array).

var items = new List<int> { 10, 20, 30, 40 }; bool exists = items.Exists(x => x > 25); // true bool any = items.Any(x => x > 25); // true

The practical difference is type compatibility. Exists() requires a List<T> or T[]. Any() works with any IEnumerable<T>, including HashSet<T>, Dictionary<TKey, TValue>, LinkedList<T>, or a custom iterator. If the code already holds a List<T>, either method works. Exists() is an instance method on List<T> and avoids LINQ extension-method dispatch, but in ordinary code the performance difference is negligible.

Any() is the safer choice when the collection type may change later, because it does not couple the code to List<T> specifically.

How Any() Behaves with IQueryable

When the source is an IQueryable<T>, Any() is translated into a query expression by the underlying provider. With Entity Framework Core or LINQ to SQL, Any() typically becomes an EXISTS clause in SQL.

var hasActiveUsers = dbContext.Users.Any(u => u.IsActive);

This translates to something like:

SELECT CASE WHEN EXISTS ( SELECT 1 FROM Users WHERE IsActive = 1 ) THEN 1 ELSE 0 END

The database can evaluate the EXISTS check without returning matching rows, and relational engines often stop scanning as soon as a match is found. This is usually more efficient than loading all matching rows into memory and checking them client-side.

The same short-circuiting logic does not apply when the query is enumerated into memory first. Calling .ToList().Any() materializes the entire result set before the check runs. If the purpose is to determine whether any rows match, the query should remain as IQueryable until Any() is called.

// Materializes all matching rows into memory first bool result = dbContext.Users.Where(u => u.IsActive).ToList().Any(); // Lets the database perform the EXISTS check bool result = dbContext.Users.Any(u => u.IsActive);

The second version sends a more efficient query and avoids loading rows that are never used.

Edge Cases: Empty Collections and Null Elements

Any() returns false for an empty sequence in both overloads. This is the expected behavior: an empty collection has no elements, so it cannot contain any element that satisfies a predicate.

var empty = new List<int>(); bool any = empty.Any(); // false bool anyEven = empty.Any(n => n % 2 == 0); // false

Null elements inside the collection do not cause Any() to throw, provided the predicate handles them. The predicate receives each element as-is, including null references.

var items = new List<string?> { null, "hello", null }; bool hasNonNull = items.Any(s => s != null); // true bool hasSpecific = items.Any(s => s == "hello"); // true

A null predicate argument, however, throws ArgumentNullException. The same applies to a null source. This is consistent with the rest of the LINQ standard query operators.

One subtle behavior worth noting: Any() on a Dictionary<TKey, TValue> enumerates KeyValuePair<TKey, TValue> entries. To check whether a key exists, ContainsKey() is the correct method, not Any() with a predicate that inspects keys. ContainsKey() performs a hash lookup in O(1) time, while Any() would enumerate the entire dictionary in the worst case.

var lookup = new Dictionary<string, int> { ["alpha"] = 1, ["beta"] = 2 }; bool hasKey = lookup.ContainsKey("alpha"); // O(1) hash lookup bool hasKeyViaAny = lookup.Any(kv => kv.Key == "alpha"); // O(n) enumeration

This distinction matters in hot paths where the dictionary is large and the check is performed frequently. Choosing the right collection API for the operation is part of writing maintainable C# code that behaves predictably under load.

C# LINQ Any: Practical Usage and Code Examples | RYUSLOG DEV