TGViewer
yet another dev yet another dev @yet_another_dev · 382 subscribers
Post #148 402
👩‍💻 Пишем производительный С# код при работе с коллекциями

Сейчас я работаю над статьёй о том, как писать производительный код для работы с коллекциями. В ней будут как базовые советы для начинающих программистов, так и продвинутые. Поскольку статья ещё не готова, держите мем и фрагмент, посвящённый LINQ.

---

В большинстве случаев методы LINQ работают медленнее и используют больше памяти. Это не значит, что LINQ – это плохо. Нет, это очень крутая фича C# и, естественно, я её тоже использую. Однако в некоторых и, подчеркну, редких ситуациях для лучшей производительности стоит писать в императивном стиле. Рассмотрим несколько простых примеров.

Select vs ConvertAll vs императивный стиль


Предположим, у нас есть массив транзакций:

public record class Transaction(
Guid Id,
int Amount,
string Description);


Допустим, нужно получить поле Description для всех элементов массива _transactions. Неважно, зачем нам это, — просто нужно. 🙂 Это можно сделать с помощью Array.ConvertAll, методов Select и ToArray, или вручную. Сравним эти три способа.

// Benchmark 1 
Array.ConvertAll(_transactions,
x => x.Description);

// Benchmark 2
_transactions
.Select(x => x.Description)
.ToArray();

// Benchamrk 3
var array = new string[_transactions.Length];
for (int i = 0; i < _transactions.Length; i++) {
array[i] = _transactions[i].Description;
}

// Results
| Method | Mean | Ratio |
|------------------ |-----------:|---------:|
| ArrayConvertAll | 1,296.4 μs | -3% |
| LinqSelect | 1,343.4 μs | baseline |
| ImperativeConvert | 1,250.4 μs | -7% |


Array.ConvertAll работает на 3% быстрее, чем LINQ, а императивный стиль — на 7% быстрее. Да, разница небольшая, но методы LINQ часто используются последовательно, и в итоге суммарное отличие в производительности может оказаться более заметным.

Any vs Exists vs императивный стиль

Рассмотрим второй пример — проверка существования элемента в массиве.

// Benchmark 1
return Array.Exists(_transactions,
x => x.Amount > 1_000_00);

// Benchmark 2
return _transactions
.Any(x => x.Amount > 1_000_00);

// Benchmark 3
foreach (var t in _transactions) {
if (t.Amount > 1_000_000) return true;
}
return false;

// Results
| Method | Mean | Ratio |
|------------------ |-----------:|---------:|
| ArrayExists | 567.9 μs | -39% |
| LinqAny | 926.1 μs | baseline |
| ImperativeExists | 488.5 μs | -47% |


Array.Exists работает на 39% быстрее, чем LINQ, а императивный стиль — почти вдвое быстрее.

---

Я обязательно проверю и другие методы, а также протестирую с массивами разного размера. Но что-то мне подсказывает, что этот раздел будет называться «Избегайте LINQ».

Кстати, напишите в комментариях, с какими проблемами производительности вам приходилось сталкиваться при работе с коллекциями. Если этого ещё нет в статье, я проанализирую, сделаю бенчмарки и включу разбор в статью.
  • 👍 9
More from @yet_another_dev
  1. Sep 21, 2026Опубликовал вчера ролик в одной запрещённой в России соцсети про то, как сходил на выборы.…
  2. Sep 20, 2026Мы пришли в 7:50 и очередь уже была 🥲 Пообщались с другими людьми. Многие приехали из дру…
  3. Sep 19, 2026Post #383
  4. Sep 18, 2026Последние пару недель на чат нападают боты со спамом (прикрыл стикером). Поэтому чат тепер…
  5. Sep 17, 2026Что интересного в этой статье: 1. Потрачено $120К, а агенты суммарно отработали около 3-х…
  6. Sep 17, 2026В Microsoft переписали рантайм GitHub Copilot с TypeScript на Rust при помощи агентов. Под…
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 →