IEnumerable vs IReadOnlyList in .NET: When Should You Use Each?

If you’re working in C# and .NET, you’ll quickly run into different collection interfaces like IEnumerable and IReadOnlyList. At first glance, they seem pretty similar—both let you work with a set of items in a read-only way. So when should you use each? In this post, I’ll break down the differences, show real-world use cases, and give you code samples so you know exactly when to reach for one or the other. Quick Definitions IEnumerable The simplest way to represent a sequence of items that you can iterate over (with foreach). It doesn’t let you access by index or get the count directly. IReadOnlyList Represents a read-only list of items. You can access items by index and get the number of items, but you can’t change the collection. Code Examples Example 1: Using IEnumerable public IEnumerable GetAllProductNames() { // Could return from a database query, LINQ, etc. return products.Select(p => p.Name); } // Usage foreach (var name in GetAllProductNames()) { Console.WriteLine(name); } When to use: When you only need to iterate (loop) over the items. When the results might be streamed, generated, or filtered on-the-fly. You don’t need to know the exact number of items or their positions. Example 2: Using IReadOnlyList public IReadOnlyList GetFeaturedProducts() { // Return a fixed, materialized list return featuredProducts.AsReadOnly(); } // Usage for (int i = 0; i

May 24, 2025 - 03:50
 0
IEnumerable vs IReadOnlyList in .NET: When Should You Use Each?

If you’re working in C# and .NET, you’ll quickly run into different collection interfaces like IEnumerable and IReadOnlyList. At first glance, they seem pretty similar—both let you work with a set of items in a read-only way. So when should you use each? In this post, I’ll break down the differences, show real-world use cases, and give you code samples so you know exactly when to reach for one or the other.

Quick Definitions

  • IEnumerable

The simplest way to represent a sequence of items that you can iterate over (with foreach). It doesn’t let you access by index or get the count directly.

  • IReadOnlyList

Represents a read-only list of items. You can access items by index and get the number of items, but you can’t change the collection.

Code Examples

Example 1: Using IEnumerable

public IEnumerable<string> GetAllProductNames()
{
    // Could return from a database query, LINQ, etc.
    return products.Select(p => p.Name);
}

// Usage
foreach (var name in GetAllProductNames())
{
    Console.WriteLine(name);
}

When to use:

  • When you only need to iterate (loop) over the items.
  • When the results might be streamed, generated, or filtered on-the-fly.
  • You don’t need to know the exact number of items or their positions.

Example 2: Using IReadOnlyList

public IReadOnlyList<Product> GetFeaturedProducts()
{
    // Return a fixed, materialized list
    return featuredProducts.AsReadOnly();
}

// Usage
for (int i = 0; i < GetFeaturedProducts().Count; i++)
{
    var product = GetFeaturedProducts()[i];
    Console.WriteLine($"{i}: {product.Name}");
}

When to use:

  • When you need to access items by their index (e.g., list[0]).
  • When you want to expose the count (list.Count).
  • When you want to guarantee that the collection is fixed and can’t be changed by the consumer.
Feature IEnumerable IReadOnlyList
Can loop with foreach
Access by index
Get count
Immutable/read-only ❌ (just iterates) ✅ (read-only contract)
Deferred execution ✅ (often) ❌ (usually materialized)

How to Decide Which to Use

  • Use IEnumerable when you want to keep things simple, just need to loop, or want to allow streaming of results.

  • Use IReadOnlyList when you want the safety and convenience of a fixed, read-only list that exposes both count and index-based access.

Real-World Examples

Repository Pattern (Read-only)

  • Use IEnumerable for large datasets you want to stream or filter on demand.
  • Use IReadOnlyList for methods that return a set of results you want to lock down (like the top 10 products).

API Response

  • Use IReadOnlyList to return a clear, fixed collection (helps with serialization and contracts).

  • Use IEnumerable internally, especially when chaining LINQ queries.

Quick Tip for Juniors

  • If you want to let others loop through your data, use IEnumerable.
  • If you want to let others see how many items you have and access by index—but not modify anything—use IReadOnlyList.

Got questions or want more real-world .NET tips? Drop a comment below!