Why does Enumerable.All return true for an empty sequence?
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
Enumerable.All returning true for an empty sequence surprises many developers the first time they see it. Intuitively, people read "all elements match" and assume there must be at least one element. In formal logic, however, All models universal quantification: "for every element x in set S, predicate P(x) is true." If S is empty, there is no counterexample, so the statement is true. This is called vacuous truth.
This behavior is intentional and useful. Once understood, it helps you write cleaner predicates and avoid unnecessary special-case checks.
Core Sections
1. Observe behavior in code
No element violates the predicate, so All returns true.
2. Compare All and Any
Any answers existence; All answers universal validity.
These results are consistent and complementary.
3. Why this design is practical
Many validation flows should pass when there is nothing to validate. For example, "all optional tags are valid" should be true when no tags exist.
If tags is empty, returning true avoids extra branching and keeps semantics clean.
4. Require non-empty sequence when business rules demand it
Sometimes your domain needs "all and at least one." Express that explicitly.
Do not try to force All alone to mean non-empty validation.
5. Performance and enumeration concerns
All short-circuits on first failure. On empty sequences, it returns immediately.
If source is an iterator with side effects, remember Any and All each enumerate. Cache when needed:
6. Cross-language consistency
This behavior exists in many languages and frameworks (Python all([]) is True, Java Streams allMatch on empty returns true). Understanding this helps when moving between ecosystems.
The principle is mathematical, not C#-specific.
Common Pitfalls
- Assuming
Allimplies non-empty input and silently accepting missing data. - Writing custom loops to override
Allsemantics instead of adding explicitAny()checks. - Misreading validation outcomes when optional collections are empty by design.
- Enumerating expensive iterables multiple times with
Any()plusAll()without caching. - Treating vacuous truth as a framework bug rather than intended universal-quantifier behavior.
Summary
Enumerable.All returns true on empty sequences because it represents universal quantification and no element violates the predicate. This behavior is both mathematically correct and practically useful for optional-data validation. When business logic requires at least one item, combine Any() with All() explicitly. Once you separate existence checks from universal checks, LINQ predicates become clearer and less error-prone.
A practical way to harden this topic in real projects is to add a small operational checklist and treat it as part of your engineering standard, not a one-off fix. Start by creating one minimal failing case and one passing case that represent real input from production logs. Then automate those checks in CI so regressions are caught before release. Add lightweight instrumentation around the critical branch where this logic runs, and include structured fields that let you filter by version, environment, and error type. This gives you fast feedback when behavior changes after dependency upgrades or refactors.
For long-term maintainability on why does enumerableall return true for an empty sequence duplicate, keep one source of truth for helper logic instead of duplicating variants across services or UI layers. Document assumptions near the code, including data format, edge-case behavior, and expected fallback policy. During code review, verify that example inputs and tests cover empty values, malformed values, and high-volume scenarios. Teams that combine explicit assumptions, repeatable tests, and basic observability typically avoid the same category of bug recurring every quarter.

