TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.75K subscribers
Post #3064 2.27K
День 2548. #ЗаметкиНаПолях
Передавайте Состояние. Продолжение

Начало

Начнём с нескольких простых случаев. Первый максимально прост - агрегирующая функция:
public static TAccumulate 
Aggregate<TSource,TAccumulate>(
this IEnumerable<TSource> source,
TAccumulate seed,
Func<TAccumulate,TSource,TAccumulate> func);

Это метод расширения, который перебирает перечислимый объект. Он принимает контекст в виде параметра seed. У него есть функция, которая принимает контекст и элемент перечисляемого объекта. Тот факт, что он возвращает значение типа контекста, является особенностью агрегирующей функции. Это не имеет ничего общего с идеей передачи контекста. Использование:
var sumOfEven = numbers
.Aggregate(
0,
static (a, item) =>
a + (item % 2 == 0 ? 1 : 0));

Как видите, мы передали контекст и использовали статическую лямбда-функцию, чем избежали захвата контекста.

Следующий пример основан на методе, который принимает делегат и некоторое состояние. В данном случае мы рассматриваем одну из перегрузок AddOrUpdate из ConcurrentDictionary:
TValue AddOrUpdate<TArg>(TKey key, 
Func<TKey,TArg,TValue> addValueFactory,
Func<TKey,TValue,TArg,TValue> updateValueFactory,
TArg factoryArgument);

ConcurrentDictionary — словарь, который может обрабатывать одновременный доступ нескольких потоков. Один из распространённых сценариев — добавление или обновление значения. Вот не самый удачный пример его использования (просто для демонстрации):
var counters = 
new ConcurrentDictionary<string, long>();

counters.AddOrUpdate("tag",
static (_, v) => v, // задаём значение
static (_, prev, update) => prev + update, // обновляем
1); // начальное значение

Состояния такого счетчика:
1. Счётчик для конкретного ключа не существует и требуется его создать.
Нужен ключ и делегат для создания значения, который принимает ключ и контекст.
2. Счётчик для конкретного ключа существует и требуется его обновить.
Аналогично, но здесь потребуется ещё один параметр – предыдущее значение.

Синхронизация их выполнения остаётся на усмотрение реализации словаря. Вы можете быть уверены, что после завершения работы этого метода возвращаемое значение будет тем, которое было установлено одним из методов. Обратите внимание: благодаря использованию дополнительного параметра контекста можно использовать статические лямбда-функции! Захват контекста не требуется.

Окончание следует…

Источник:
https://blog.scooletz.com/2025/10/08/pass-the-state
More from @netdeveloperdiary
  1. Sep 28, 2026День 2798. #Оффтоп Утиная Типизация в C# с Помощью Перехватчиков. Часть 2 Некоторое время…
  2. Sep 27, 2026День 2797. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Окончание Начало Продол…
  3. Sep 26, 2026День 2796. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Продолжение Начало Три…
  4. Sep 25, 2026День 2795. #ЗаметкиНаПолях #AI Рабочий процесс с Copilot для .NET. Начало Проблема с позиц…
  5. Sep 24, 2026День 2794. #Оффтоп #Здоровье Сегодня будет необычный пост. Завтра в Москве стартует конфер…
  6. Sep 23, 2026День 2793. #ЗаметкиНаПолях #SQL 10 Редких Возможностей SQL, Которые Стоит Знать Каждому. Ч…
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 →