IQueryable vs IEnumerable in C#
If you’ve ever worked with LINQ, Entity Framework, or any data-heavy .NET application, you’ve definitely used IEnumerable and IQueryable. They look similar, they both support LINQ, and they both return collections — so what’s the real difference?
This guide breaks it down with definitions, execution behavior, EF Core examples, performance insights, and real-world scenarios.
What Is IEnumerable?
IEnumerable represents an in-memory collection.
It is used for LINQ to Objects.
Key characteristics
- Works in memory
- Executes on the client side
- Loads all data first, then filters
- Best for collections already in memory
- Supports deferred execution
Example
IEnumerable<int> numbers = new List<int> { 1, 2, 3, 4 };
var result = numbers.Where(n => n > 2);
// Filtering happens in memory
What Is IQueryable?
IQueryable represents a queryable data source, usually a database.
It is used for LINQ to SQL / LINQ to Entities.
Key characteristics
- Works with remote data sources (SQL, NoSQL, APIs)
- Executes on the server side
- Translates LINQ into SQL
- Fetches only the required data
- Supports expression trees
Example
IQueryable<User> users = db.Users;
var result = users.Where(u => u.IsActive);
// Filtering happens in SQL
Execution Difference (The Most Important Part)
IEnumerable
- Pulls all rows into memory
- Applies filters after loading
- Can cause massive performance issues with large datasets
IQueryable
- Converts your LINQ into SQL
- Database does the filtering
- Only returns the needed rows
- Much more efficient for large datasets
Side‑by‑Side Comparison
| Feature | IEnumerable | IQueryable |
|---|---|---|
| Executes in | Memory | Database |
| Suitable for | Collections | EF Core, SQL |
| Deferred execution | ✔️ Yes | ✔️ Yes |
| Translates to SQL | ❌ No | ✔️ Yes |
| Performance | Slower for large data | Faster for large data |
| Filtering | Client-side | Server-side |
| Use case | In-memory operations | Database queries |
EF Core Example (Critical Difference)
Using IEnumerable (Bad)
var users = db.Users.ToList(); // Loads ALL users
var active = users.Where(u => u.IsActive);
// Filtering happens in memory
Using IQueryable (Good)
var active = db.Users.Where(u => u.IsActive);
// Translates to: SELECT * FROM Users WHERE IsActive = 1
Real‑World Scenarios
Scenario 1: Fetching users from a database
Use IQueryable.
var admins = db.Users.Where(u => u.Role == "Admin");
Scenario 2: Filtering a list already in memory
Use IEnumerable.
var filtered = myList.Where(x => x.IsValid);
Scenario 3: Paging (Skip/Take)
Use IQueryable — SQL handles paging efficiently.
var page = db.Orders
.OrderBy(o => o.Id)
.Skip(20)
.Take(10);
Scenario 4: Complex business logic
Use IEnumerable when logic cannot be translated to SQL.
var result = db.Users
.AsEnumerable() // Switch to IEnumerable
.Where(u => CustomValidation(u));
Interview‑Ready Summary
- Use IQueryable for database queries
- Use IEnumerable for in-memory operations
- IQueryable = SQL translation + server-side filtering
- IEnumerable = client-side filtering
- IQueryable is more efficient for large datasets
Top comments (0)