When to Use IEnumerable vs IQueryable in C#
IEnumerable<T> is for in-memory collections and executes queries in the application. IQueryable<T> is for out-of-memory data sources like databases and translates queries to the data source's native language (like SQL).QL).
Use IEnumerable<T> when working with in-memory collections (arrays, lists, etc.). Use IQueryable<T> when querying databases or external data sources to enable server-side filtering and reduce data transfer.
IEnumerable uses deferred execution with LINQ to Objects, while IQueryable uses expression trees that can be translated to query languages like SQL.
Sample Data
C# Example Code
// IEnumerable - in-memory collection
List<Product> products = new List<Product>
{
new Product { Id = 1, Name = "Laptop", Price = 1200, Category = "Electronics" },
new Product { Id = 2, Name = "Mouse", Price = 25, Category = "Electronics" },
new Product { Id = 3, Name = "Desk", Price = 350, Category = "Furniture" },
new Product { Id = 4, Name = "Chair", Price = 200, Category = "Furniture" },
new Product { Id = 5, Name = "Monitor", Price = 400, Category = "Electronics" }
};Using IEnumerable for In-Memory Filtering
C# Example Code
// IEnumerable - filtering happens in memory
IEnumerable<Product> enumerable = products;
var expensiveProducts = enumerable.Where(p => p.Price > 100);
Console.WriteLine("IEnumerable (in-memory filtering):");
foreach (var product in expensiveProducts)
{
Console.WriteLine($"{product.Name}: ${product.Price}");
}Using IQueryable for Expression-Based Queries
C# Example Code
// IQueryable - can be translated to SQL or other query language
IQueryable<Product> queryable = products.AsQueryable();
var electronicsQuery = queryable.Where(p => p.Category == "Electronics");
Console.WriteLine("\nIQueryable (expression-based):");
foreach (var product in electronicsQuery)
{
Console.WriteLine($"{product.Name}: ${product.Price}");
}Query Composition and Chaining
C# Example Code
// Demonstrating query composition
Console.WriteLine("\nQuery Composition:");
var complexQuery = queryable
.Where(p => p.Price > 100)
.OrderBy(p => p.Price)
.Select(p => new { p.Name, p.Price });
foreach (var item in complexQuery)
{
Console.WriteLine($"{item.Name}: ${item.Price}");
}Performance Patterns and Query Translation
C# Example Code
// IEnumerable: All filtering after ToList()
Console.WriteLine("\nIEnumerable Performance Pattern:");
var inMemory = products
.Where(p => p.Category == "Electronics") // Happens in memory
.ToList(); // Already in memory
Console.WriteLine($"Found {inMemory.Count} electronics");
// IQueryable: Filtering would be done at data source
// (In real scenarios with Entity Framework or LINQ to SQL)
Console.WriteLine("\nIQueryable Pattern (simulated DB query):");
var dbQuery = products.AsQueryable()
.Where(p => p.Category == "Electronics") // Would translate to SQL WHERE
.Select(p => p.Name); // Would translate to SQL SELECT
Console.WriteLine($"Query created (would execute on database)");
// Conversion between them
IEnumerable<Product> fromQueryable = queryable.AsEnumerable();
IQueryable<Product> fromEnumerable = enumerable.AsQueryable();Product Class
C# Example Code
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
}