Skip to content

Latest commit

 

History

History
236 lines (161 loc) · 11.2 KB

File metadata and controls

236 lines (161 loc) · 11.2 KB
layout default
title 📚 В чём разница между `IEnumerable<T>` и `IQueryable<T>`?
description
author Dvurechensky
date 2025-08-28
published true
tags
IEnumerable
IQueryable
C#

📚 В чём разница между `IEnumerable'T'` и `IQueryable'T'`?

Typing SVG

Static Badge

✨ Оглавление

⬆ Вернуться к главной


1️⃣ Основные определения

IEnumerable<T>

  • Определён в System.Collections.Generic.

  • Позволяет перебирать коллекцию элементов в памяти (in-memory).

  • Поддерживает только LINQ to Objects.

  • Выполнение немедленное только при обращении к коллекции (foreach).

  • Методы расширения LINQ для IEnumerable<T>:

    • Where, Select, OrderBy, Take, Skip.
  • Отложенное исполнение (deferred execution) — да, но только в памяти.

IQueryable<T>

  • Определён в System.Linq.

  • Расширяет IEnumerable<T>:

    • Добавляет Expression для построения дерева выражений.
  • Используется для удалённого источника данных (например, БД через Entity Framework, LINQ to SQL).

  • LINQ-запросы не выполняются сразу; создаётся дерево выражений.

  • Выполнение (execution) происходит только при материализации данных (ToList(), ToArray(), foreach).


2️⃣ Deferred Execution (отложенное выполнение)

  • IEnumerable

    • Отложенное выполнение выполняется после того, как объект в памяти доступен.

    • Пример:

      var query = list.Where(x => x > 5); // ещё не выполняется
      foreach(var n in query) { ... }     // выполняется здесь
  • IQueryable

    • Отложенное выполнение формирует SQL-запрос (или другой провайдерский запрос).

    • Пример EF:

      var query = db.Users.Where(u => u.Age > 18); // строится Expression tree
      var result = query.ToList();                 // выполняется SQL-запрос

3️⃣ Где выполняется обработка

Характеристика IEnumerable IQueryable
Источник данных В памяти (объекты .NET) Внешний источник (БД, веб-сервис)
SQL/провайдер Нет Да, формирует запрос к источнику
LINQ методы Все выполняются в памяти Выражения преобразуются в Expression Tree → выполняются удалённо
Поддержка сложных запросов Ограничена (в памяти) Полная, если провайдер поддерживает

4️⃣ Примеры различий

IEnumerable<T>

List<int> numbers = new() {1,2,3,4,5};
var query = numbers.Where(n => n > 2).Select(n => n * 2);

foreach(var n in query) Console.WriteLine(n); // выполняется в памяти
  • Все элементы уже в памяти.
  • Where и SelectC# делегаты.

IQueryable<T> (например, Entity Framework)

var query = db.Users
    .Where(u => u.Age > 18)
    .Select(u => new { u.Name, u.Age });

var result = query.ToList(); // SQL запрос к БД выполняется здесь
  • Where и Select → выражения, переводятся в SQL.
  • Эффективно: фильтруются только нужные данные.

5️⃣ Когда использовать

  • IEnumerable

    • Когда данные уже загружены в память.
    • Для небольших коллекций и локальных операций.
  • IQueryable

    • Когда нужно формировать запрос к БД или удалённым источникам.
    • Для больших данных, чтобы фильтровать/проецировать на стороне сервера.

6️⃣ Производительность

  • IEnumerable<T>:

    • Перебор всех элементов → O(n).
    • Если фильтруешь много данных → всё уже загружено в память → дорого.
  • IQueryable<T>:

    • Генерирует оптимальный запрос к серверу.
    • Обрабатывает фильтрацию на стороне источника → экономия памяти и сети.
  • Подводный камень:

    • Частое комбинирование IEnumerable<T> и IQueryable<T> может вынести всю коллекцию в память раньше времени.

7️⃣ Каверзные моменты на собеседовании

  1. Что происходит при смешении IEnumerable<T> и IQueryable<T>?

    var result = db.Users.AsEnumerable().Where(u => u.Age > 18);
    • AsEnumerable() переводит IQueryable в IEnumerable → дальнейшие фильтры выполняются в памяти, а не в SQL.
  2. Deferred execution

    • Часто спрашивают, когда именно выполняется запрос. Ответ: только при фактической итерации (foreach, ToList(), Count(), First()).
  3. Что такое Expression Tree?

    • В IQueryable каждый метод LINQ создаёт Expression → можно преобразовать в SQL или другой провайдерский код.
  4. Можно ли использовать сложные функции C# в IQueryable?

    • Нет, только то, что провайдер может транслировать (например, EF Core может не поддерживать все методы).
  5. Память

    • IEnumerable работает в памяти → нагрузка на RAM.
    • IQueryable может использовать отложенную выборку → меньше памяти.
  6. Вызовы методов

    • IEnumerable<T> — методы LINQ вызываются в C# коде.
    • IQueryable<T> — методы формируют дерево выражений → выполняются в источнике данных.

8️⃣ Пример различий

// IQueryable -> SQL
var query1 = db.Users.Where(u => u.Name.StartsWith("A"));
// SQL генерируется при ToList()

// IEnumerable -> в памяти
var query2 = db.Users.ToList().Where(u => u.Name.StartsWith("A"));
// Все пользователи загружены, фильтрация в памяти
  • query1 — эффективнее.
  • query2 — грузим всё в память → неэффективно для больших таблиц.

9️⃣ Таблица основных отличий

Характеристика IEnumerable IQueryable
Namespace System.Collections.Generic System.Linq
Основа Делегаты C# Expression Tree
Источник данных In-memory Remote / DB / External
Deferred execution Да Да, с генерацией выражения
SQL / Provider translation Нет Да
Преобразования LINQ to Objects LINQ to Entities / LINQ to SQL
Производительность Может быть медленнее для больших данных Оптимизировано для источника
Поддержка методов C# Все Только методы, поддерживаемые провайдером
Аллокация памяти Вся коллекция Только нужные элементы

⬆ Вернуться к главной

✨Dvurechensky✨