Обзор вопросов по языка програмиированию C# и технологии NET
IEnumerable<T>
System.Collections.Generic
.foreach
).Методы расширения LINQ для IEnumerable<T>
:
Where
, Select
, OrderBy
, Take
, Skip
.deferred execution
) — да, но только в памяти.IQueryable<T>
System.Linq
.Расширяет IEnumerable<T>
:
Expression
для построения дерева выражений.execution
) происходит только при материализации данных (ToList()
, ToArray()
, foreach
).**IEnumerable
Пример:
var query = list.Where(x => x > 5); // ещё не выполняется
foreach(var n in query) { ... } // выполняется здесь
**IQueryable
Пример EF:
var query = db.Users.Where(u => u.Age > 18); // строится Expression tree
var result = query.ToList(); // выполняется SQL-запрос
Характеристика | IEnumerable |
IQueryable |
---|---|---|
Источник данных | В памяти (объекты .NET) | Внешний источник (БД, веб-сервис) |
SQL/провайдер | Нет | Да, формирует запрос к источнику |
LINQ методы | Все выполняются в памяти | Выражения преобразуются в Expression Tree → выполняются удалённо |
Поддержка сложных запросов | Ограничена (в памяти) | Полная, если провайдер поддерживает |
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
и Select
— C# делегаты.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.**IEnumerable
**IQueryable
IEnumerable<T>
:
IQueryable<T>
:
Подводный камень:
IEnumerable<T>
и IQueryable<T>
может вынести всю коллекцию в память раньше времени.Что происходит при смешении IEnumerable<T>
и IQueryable<T>
?
var result = db.Users.AsEnumerable().Where(u => u.Age > 18);
AsEnumerable()
переводит IQueryable
в IEnumerable
→ дальнейшие фильтры выполняются в памяти, а не в SQL.Deferred execution
foreach
, ToList()
, Count()
, First()
).Что такое Expression Tree?
IQueryable
каждый метод LINQ создаёт Expression
→ можно преобразовать в SQL или другой провайдерский код.Можно ли использовать сложные функции C# в IQueryable
?
Память
IEnumerable
работает в памяти → нагрузка на RAM.IQueryable
может использовать отложенную выборку → меньше памяти.Вызовы методов
IEnumerable<T>
— методы LINQ вызываются в C# коде.IQueryable<T>
— методы формируют дерево выражений → выполняются в источнике данных.// 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
— грузим всё в память → неэффективно для больших таблиц.Характеристика | 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✨