Difference between IEnumerable Count and Length
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
IEnumerable<T> does not have a built-in Length property, and that is where most confusion starts. In .NET, Length, Count, and LINQ Count() look similar from the call site, but they have different costs and apply to different collection types.
Length, Count, and Count()
Length is a property on arrays and a few fixed-size types such as string. It is constant-time because the runtime already knows the size.
Count is also a property, but it belongs to collection interfaces and classes such as List<T>, Dictionary<TKey, TValue>, ICollection<T>, and IReadOnlyCollection<T>.
Count() is different. It is a LINQ extension method for IEnumerable<T>. If the source sequence exposes a fast count through one of the supported collection interfaces, LINQ uses that. Otherwise, it enumerates the entire sequence.
That last example looks cheap, but the method call can be much more expensive than a property access when the sequence is deferred.
Why IEnumerable<T> Has No Length
IEnumerable<T> only promises one thing: you can iterate over it. It does not promise random access, fixed size, or even repeatable results.
A sequence may come from:
- a database query
- a generator using
yield return - a file stream
- a network-backed API
In all of those cases, "how many items are there" may require iterating through the whole sequence.
Running this prints each yielded item because Count() consumes the iterator.
Performance Implications
For arrays and lists, prefer the property when you know the concrete type. It communicates intent and avoids unnecessary abstraction.
If you only have IEnumerable<T>, Count() is fine when you genuinely need the count and understand the source may be enumerated. Problems start when code calls Count() repeatedly inside loops or on expensive deferred queries.
Bad pattern:
If the source does not expose a fast count, that loop recomputes the count every iteration. Materialize once if needed.
Safe Patterns When You Only Have IEnumerable<T>
If your method accepts IEnumerable<T>, decide whether you need:
- streaming behavior
- a count only
- indexed access
For count only, use TryGetNonEnumeratedCount in newer .NET versions. It avoids enumeration when possible.
If you need indexing or repeated passes, convert to an appropriate collection type first.
That makes the cost explicit instead of hiding it behind repeated LINQ calls.
API Design Guidance
Method signatures matter. If your code needs count and index access, accept IReadOnlyList<T> or ICollection<T> instead of plain IEnumerable<T>.
This is clearer than accepting IEnumerable<T> and then assuming the sequence can be counted and indexed cheaply.
A stronger signature also helps callers understand what shape of data the method expects.
Common Pitfalls
- Expecting
IEnumerable<T>to have aLengthproperty. - Assuming
Count()is always constant-time. - Calling
Count()repeatedly on deferred queries. - Accepting
IEnumerable<T>in APIs that really require indexing. - Forgetting that counting an iterator can consume expensive work.
Summary
- '
Lengthis a property for arrays and similar fixed-size types.' - '
Countis a property for collection types such asList<T>.' - '
Count()is a LINQ method forIEnumerable<T>and may enumerate the source.' - Use concrete collection interfaces when your API needs more than simple iteration.
- Treat counting deferred sequences as potentially expensive unless you know the source.

