Sobes.tech
Назад к вопросам
Junior — Middle
55

Как отличить IEnumerable от IQueryable и в каких случаях используют каждый из них?

Ответ от нейросети

sobes.tech AI

Что хотят услышать интервьюеры:

IEnumerable используют для работы с уже полученными данными в памяти, а IQueryable — когда запрос должен быть переведён в другой формат и выполнен на источнике данных, например в базе. Главная разница в том, где выполняется фильтрация и другие операции: в памяти или на стороне провайдера. Обычно IEnumerable — для коллекций, IQueryable — для запросов к БД через ORM.

Определение:

IEnumerable<T> — это интерфейс для последовательности объектов, по которой можно итерироваться. Он подходит для данных, которые уже загружены в память, и LINQ-операции над ним выполняются в памяти.

IQueryable<T> наследуется от IEnumerable<T>, но добавляет возможность строить выражение запроса. Такой запрос не выполняется сразу: он передаётся провайдеру данных, который может преобразовать его, например, в SQL и выполнить на сервере.

Пример использования:

using System;
using System.Collections.Generic;
using System.Linq;

var numbers = new List<int> { 1, 2, 3, 4, 5 };

// IEnumerable: фильтрация уже загруженной коллекции в памяти
IEnumerable<int> inMemoryResult = numbers.Where(n => n > 2);

// IQueryable: запрос строится как выражение и может быть выполнен провайдером
IQueryable<int> queryableResult = numbers.AsQueryable().Where(n => n > 2);

Console.WriteLine(string.Join(", ", inMemoryResult));    // 3, 4, 5
Console.WriteLine(string.Join(", ", queryableResult));   // 3, 4, 5

На практике с базой данных это выглядит так: IQueryable позволяет не загружать все записи сразу, а отправить в БД только нужный WHERE, SELECT, ORDER BY.

Пояснение кода:

В примере numbers — обычный список в памяти.
Where(n => n > 2) для IEnumerable выполняется как перебор элементов в приложении.
AsQueryable() оборачивает коллекцию в IQueryable, после чего запрос выражается как дерево выражений, а не сразу как готовая операция.
В случае с реальной БД провайдер мог бы преобразовать этот запрос в SQL и выполнить его на сервере.
Для List<T> обе версии дадут похожий результат, но разница проявляется именно при работе с внешним источником данных.

Ключевые моменты:

  • IEnumerable — для данных в памяти и построчной обработки в приложении.
  • IQueryable — для построения запроса к внешнему источнику данных.
  • IQueryable позволяет отложить выполнение и перенести фильтрацию на сторону БД.
  • Не стоит рано вызывать ToList(), если нужно дальше фильтровать данные на сервере.
  • IQueryable полезен с ORM и провайдерами LINQ, IEnumerable — с коллекциями, массивами, списками.
  • Если запрос уже выполнен и данные загружены, дальнейшая работа идёт через IEnumerable.