Ответ
Разница заключается в месте выполнения запроса и, как следствие, в его эффективности.
| Характеристика | IEnumerable<T> |
IQueryable<T> |
|---|---|---|
| Пространство имен | System.Collections |
System.Linq |
| Цель | Работа с коллекциями в памяти (LINQ to Objects). | Работа с внешними источниками данных (LINQ to Entities, LINQ to SQL). |
| Место выполнения | Запрос выполняется на стороне клиента (в памяти приложения). | Запрос транслируется в язык источника (например, SQL) и выполняется на стороне сервера (БД). |
| Философия | «Принеси все данные, потом отфильтруй». | «Расскажи, что нужно, я сам отфильтрую и принесу результат». |
Наглядный пример с Entity Framework Core:
// Контекст базы данных
var dbContext = new AppDbContext();
// ПЛОХО: Использование IEnumerable
IEnumerable<Product> productsEnum = dbContext.Products; // Неявное приведение
var cheapProductsEnum = productsEnum.Where(p => p.Price < 50).ToList();
// Что происходит:
// 1. `dbContext.Products` выполняется как SQL: SELECT * FROM Products
// 2. ВСЕ продукты загружаются в память приложения.
// 3. Фильтр `Where(p => p.Price < 50)` применяется в памяти к уже загруженным данным.
// ХОРОШО: Использование IQueryable
IQueryable<Product> productsQuery = dbContext.Products;
var cheapProductsQuery = productsQuery.Where(p => p.Price < 50).ToList();
// Что происходит:
// 1. Запрос НЕ выполняется сразу. Строится выражение.
// 2. При вызове `.ToList()` выражение транслируется в SQL:
// SELECT * FROM Products WHERE Price < 50
// 3. В память загружаются ТОЛЬКО отфильтрованные данные.
Ключевые выводы:
- Используйте
IQueryable, когда работаете с ORM (EF Core) и хотите, чтобы фильтрация, сортировка и пагинация выполнялись на стороне БД. Это критически важно для производительности. - Используйте
IEnumerable, когда источник данных уже находится в памяти (массив, список) или после того, как вы материализовалиIQueryable(вызвали.ToList(),.ToArray()). - Материализация: Вызов методов, возвращающих коллекции (
.ToList(),.First()), или перечисление черезforeachприводит к выполнению запроса и переходу отIQueryableкIEnumerable.
Видео-ответы
▶
Пробное Middle C# собеседование (мок-интервью). Часть 2
▶
Тестовое собеседование на .NET Middle разработчика
▶
Меньше 2 лет опыта это Junior или Middle? | Тестовое собеседование C#
▶
Собес на стажика с таймтрекером, пишущего на dotnet ಠ_ಠ #net #csharp
▶
Собеседование на .NET разработчика (backend)
▶
Tech Interview Fest | Моковое cобеседование для C# Junior | Solvery + @DotNetRu