TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.77K subscribers
Post #1966 1.46K
День 1618. #ЗаметкиНаПолях
LINQ: Select.Where или Where.Select?
LINQ — очень мощный инструмент для запросов данных. Поскольку большинство функций построены на основе IEnumerable<T> и в большинстве случаев он также возвращает IEnumerable<T>, очень легко объединять несколько функций в цепочку. Возникает вопрос: есть ли разница между Select.Where или Where.Select?

Сначала замечу, что далее мы рассматриваем только коллекции «в памяти», и не IQueryable<T>. Там порядок зависит в основном от провайдера, поэтому Entity Framework и LINQ to SQL могут давать разные результаты.

Рассмотрим следующий пример кода:
var users = GetAllUsers();

// Вариант 1
users.Where(u => u.IsStudent)
.Select(u =>
new { u.FirstName, u.LastName, u.IsStudent });

// Вариант 2
users.Select(u =>
new { u.FirstName, u.LastName, u.IsStudent })
.Where(u => u.IsStudent);

Результат обоих запросов будет одинаковым. Но это не означает, что они делают одно и то же. Первый вариант сначала отфильтрует всех пользователей, которые не являются студентами, а затем создаст анонимный тип. Второй вариант сначала создаст анонимный тип для всех пользователей, а затем отфильтрует тех, кто не является студентами. Какой запрос быстрее?

Скорее всего, первый, т.к. второй вариант создаст анонимный тип для всех пользователей, даже для тех, кто не является студентом. Т.е. второму варианту придётся проделать больше работы. Для больших списков разница может быть значительна. Как правило, всегда нужно пытаться отфильтровать как можно больше, прежде чем начинать создавать новые объекты. Аналогично с OrderBy. Если список предварительно не фильтруется, OrderBy должен будет проверить гораздо больше записей.

А теперь рассмотрим такой пример:
// вариант 1
users.Where(u => u.IsStudent && u.Age > 30);

// вариант 2
users.Where(u => u.IsStudent)
.Where(u => u.Age > 30);

Опять же семантически они делают одно и то же. Результат будет одинаковым, но способ его достижения - разным. Первый вариант сразу проверит оба условия. Второй вариант (хотя это и не очевидно) также пройдёт по списку только один раз, но здесь возникнут дополнительные накладные расходы на вызов нескольких функций. Кстати, автор оригинальной статьи (см. источник ниже) считает, что этими расходами можно пренебречь. Однако, судя по моим бенчмаркам (см. картинку ниже) разница в некоторых средах может быть довольно существенной (хотя, в .NET 8 выполнение заметно оптимизировали).

Если всё же не обойтись без нескольких предложений Where, имеет смысл поставить лучший фильтр в начале, либо попробовать реорганизовать все фильтры в один метод:
private bool IsStudentAndOlderThan30(User user)
{
return user.IsStudent && user.Age > 30;
}

users.Where(IsStudentAndOlderThan30);

Источник: https://steven-giesel.com/blogPost/57ed9867-4afd-4d02-9f35-e0941bc6f715
  • 👍 21
More from @netdeveloperdiary
  1. Oct 11, 2026День 2811. #ВопросыНаСобеседовании Марк Прайс предложил свой набор из 60 вопросов (как тех…
  2. Oct 10, 2026День 2810. #ЧтоНовенького #VSCode Более Быстрый и Лёгкий C# Dev Kit Мы, разработчики, люби…
  3. Oct 9, 2026День 2809. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Окончание Начало 3.…
  4. Oct 8, 2026День 2808. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Начало В ИТ есть се…
  5. Oct 7, 2026День 2807. #ЗаметкиНаПолях Типы Коллекций в .NET, Которые Стоит Попробовать. Окончание Нач…
  6. Oct 6, 2026🦈 Открытое собеседование на Middle C# | 6 октября, 19:00 МСК Приглашаем на открытое собес…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →