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

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!