C#
IEnumerable
Null Check
Programming Tips
.NET

How to check if IEnumerable is null or empty?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Checking whether an IEnumerable is null or empty sounds simple, but there is one detail that matters: IEnumerable may represent a lazy sequence, not a materialized collection. That means a null-or-empty check can sometimes trigger enumeration.

The most common practical answer is source == null || !source.Any(). It is concise, readable, and efficient for most cases because Any() stops as soon as it finds the first element.

The Basic Check

For an IEnumerable<T>, the usual pattern is:

csharp
1using System.Collections.Generic;
2using System.Linq;
3
4IEnumerable<int> numbers = GetNumbers();
5
6bool isNullOrEmpty = numbers == null || !numbers.Any();

This works because:

  • the null check protects against NullReferenceException
  • 'Any() returns quickly once it sees the first item'
  • the code reads almost like plain English

For most application code, this is all you need.

A Reusable Extension Method

If you perform this check often, wrap it in an extension method:

csharp
1using System.Collections.Generic;
2using System.Linq;
3
4public static class EnumerableExtensions
5{
6    public static bool IsNullOrEmpty<T>(this IEnumerable<T>? source)
7    {
8        return source == null || !source.Any();
9    }
10}

Usage:

csharp
1if (numbers.IsNullOrEmpty())
2{
3    Console.WriteLine("No values available");
4}

This improves readability, especially in business logic where the null-or-empty concept appears frequently.

Be Aware of Lazy Sequences

IEnumerable<T> is not always a list. It might be a LINQ query, a generator, or a streaming sequence.

That means Any() may execute part of the query. For example:

csharp
1IEnumerable<int> values = Enumerable.Range(1, 10)
2    .Where(x =>
3    {
4        Console.WriteLine($"Testing {x}");
5        return x > 5;
6    });
7
8bool empty = !values.Any();

The query does not run until Any() is called. Then it starts enumerating until it finds a matching item or reaches the end.

That behavior is usually fine, but it is important to remember that checking emptiness can still have cost or side effects if the sequence is expensive or stateful.

Fast Path for Real Collections

Sometimes you want to avoid even a single-element enumeration when the source is already a collection with a count.

csharp
1using System.Collections.Generic;
2using System.Linq;
3
4public static class EnumerableExtensions
5{
6    public static bool IsNullOrEmpty<T>(this IEnumerable<T>? source)
7    {
8        if (source == null)
9            return true;
10
11        if (source is ICollection<T> collection)
12            return collection.Count == 0;
13
14        return !source.Any();
15    }
16}

This is a nice refinement because it uses Count directly for collections and falls back to Any() for everything else.

When Not to Check Twice

A common anti-pattern is:

csharp
1if (numbers != null && numbers.Any())
2{
3    foreach (var n in numbers)
4    {
5        Console.WriteLine(n);
6    }
7}

For a lazy sequence, this can enumerate twice: once for Any() and once for foreach. If the sequence is expensive, consider materializing it first or restructuring the code.

That is one reason IEnumerable<T> is different from List<T>. The abstraction is powerful, but it hides whether the sequence is cached or recomputed.

Common Pitfalls

The biggest mistake is calling Any() without a null check. Any() itself does not handle null sources.

Another common issue is assuming every IEnumerable<T> is a cheap in-memory collection. Some are queries, streams, or one-shot iterators.

A third problem is checking Any() and then enumerating again without realizing the sequence may run twice.

Summary

  • The usual check is source == null || !source.Any().
  • 'Any() is efficient because it stops after the first item.'
  • An extension method can make the pattern easier to reuse.
  • For real collections, a Count fast path can avoid enumeration.
  • Be careful with lazy sequences, because even an emptiness check may execute part of the query.

Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.