C# в 2026-м: от
Зачем просто писать асинхронный код, если можно запустить команду автономных агентов? В новом году Enterprise-разработка переходит на рельсы мультиагентности.
Прокачайте свой стек на курсе по AI-агентам:
— реализуйте паттерн
— свяжите бизнес-логику с внешними API через
— освойте протокол
— внедрите
Ваш идеальный дипломный проект: автономная группа агентов, решающая задачи за целый отдел.
❄️ До 12 января действует акция «3 в 1»: курс по ИИ-агентам + 2 курса в подарок.
Стать архитектором агентов
Task.Run к Agent.RunЗачем просто писать асинхронный код, если можно запустить команду автономных агентов? В новом году Enterprise-разработка переходит на рельсы мультиагентности.
Прокачайте свой стек на курсе по AI-агентам:
— реализуйте паттерн
ReAct для принятия решений внутри .NET систем;— свяжите бизнес-логику с внешними API через
n8n;— освойте протокол
MCP для межсистемного взаимодействия агентов;— внедрите
RAG для мгновенной обработки корпоративных данных.Ваш идеальный дипломный проект: автономная группа агентов, решающая задачи за целый отдел.
❄️ До 12 января действует акция «3 в 1»: курс по ИИ-агентам + 2 курса в подарок.
Стать архитектором агентов
🎉4
🔢 Сортировка строк с числами
Мы уже упоминали эту новость из Preview. Сейчас она в .NET 10, и стоит напомнить, что проблема file1, file10, file2 больше не актуальна.
Суть в
Протестить:
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#лучшее_из_библиотеки_2025
Мы уже упоминали эту новость из Preview. Сейчас она в .NET 10, и стоит напомнить, что проблема file1, file10, file2 больше не актуальна.
Суть в
CompareOptions.NumericOrdering. Issue #13979 висела с 2015, и вот она решена нативно. Флаг заставляет сравнивать цифры как числа, а не посимвольно, так что последовательности вроде версий или имен файлов идут правильно.Протестить:
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
var files = new List<string> { "file10", "file2", "file1", "file20" };
// Обычная сортировка
var sortedLex = files.OrderBy(f => f).ToList();
Console.WriteLine("Лексикографическая: " + string.Join(", ", sortedLex));
// file1, file10, file20, file2
// Числовая сортировка
var comparer = StringComparer.Create(CultureInfo.CurrentCulture, CompareOptions.NumericOrdering);
var sortedNumeric = files.OrderBy(f => f, comparer).ToList();
Console.WriteLine("Числовая: " + string.Join(", ", sortedNumeric));
// file1, file2, file10, file20
📍 Навигация: Вакансии • Задачи • Собесы
#лучшее_из_библиотеки_2025
Please open Telegram to view this post
VIEW IN TELEGRAM
👍37❤1🔥1
Мы уже делились этим материалом весной, и сейчас самое время напомнить. Scalar это интерактивный UI для OpenAPI, который можно подключить к ASP.NET Core и получить более приятную документацию, чем стандартный Swagger UI.
Процесс установки не сложный, а результат превзойдет все ожидания.
📍 Навигация: Вакансии • Задачи • Собесы
#лучшее_из_библиотеки_2025
Please open Telegram to view this post
VIEW IN TELEGRAM
🥰4❤2❤🔥1
Мы уже показывали этот трюк, и сейчас напомним, потому что он спасает часы ручного набора классов. В
Visual Studio Edit → Paste Special → Paste JSON As Classes генерирует классы из JSON в буфере, включая атрибуты сериализации.Пример:
"Colors": [
{
"numberKey": 1,
"isPrimary": true,
"listColors": ["Red", "Blue", "Yellow"]
},
{
"numberKey": 2,
"isPrimary": false,
"listColors": ["Purple", "Green", "Orange"]
}
]
}
Сгенерированный C# код:
public class Root
{
public Color[] Colors { get; set; }
}
public class Color
{
public int NumberKey { get; set; }
public bool IsPrimary { get; set; }
public string[] ListColors { get; set; }
}
📍 Навигация: Вакансии • Задачи • Собесы
#лучшее_из_библиотеки_2025
Please open Telegram to view this post
VIEW IN TELEGRAM
👍21😁3🔥2❤1⚡1
Тогда мы уже выкладывали похожий чек лист, и сейчас вспомним.
Основные принципы LINQ
✓ Понимать разницу между
IEnumerable<T> и IQueryable<T>✓ Фильтровать (
Where()) данные как можно раньше в цепочке вызовов.✓ Извлекать (
Select()) только нужные поля, а не всю сущность.✓ Использовать
Any() вместо Count() > 0 для проверки наличия элементов.✓ Избегать многократных проходов по коллекции (повторных
.Where(), .Select())✓ Знать разницу между отложенным и немедленным выполнением.
Работа с Where, Select, FirstOrDefault
✓ Не использовать
Where().FirstOrDefault() – просто FirstOrDefault().✓ Вызывать
Where() перед Select(), а не наоборот.✓ Использовать
FirstOrDefault(predicate), если проверяется только одно значение.Nullable
✓ Использовать ?? для значений, которые могут быть null.
✓ Использовать
DefaultIfEmpty() при GroupBy().Избегание дублирующих данных
✓ Использовать
Distinct() для уникальных значений.✓ Использовать
Union() для объединения без дубликатов.✓ Использовать
Except() и Intersect() для разницы между коллекциями.Помните, что LINQ — это не просто удобство, а инструмент, требующий понимания его тонкостей.
📍 Навигация: Вакансии • Задачи • Собесы
#лучшее_из_библиотеки_2025
Please open Telegram to view this post
VIEW IN TELEGRAM
👍23❤5
Мы уже разбирали ValueTask раньше, но сейчас напомним ключевые моменты. ValueTask это структура, которая может хранить либо готовый результат, либо Task, чтобы избежать аллокаций в простых случаях.
Особенности использования ValueTask:
• Повторное ожидание запрещено
Вызывать
await несколько раз для одного и того же ValueTask нельзя, так как это может привести к неожиданным результатам:ValueTask<int> task = GetValueAsync();
int value1 = await task;
int value2 = await task; // Ошибка
• Конвертация в
TaskEсли требуется передать
ValueTask в API, которое ожидает Task, можно вызвать метод .AsTask():Task<int> task = GetValueAsync().AsTask();
• Когда использовать ValueTask:
+ Операция часто завершается синхронно.
+ Создание объекта Task может быть слишком накладным.
+ Вы пишете библиотеку с высокой производительностью.
• Когда НЕ использовать ValueTask:
- Операция всегда асинхронна.
- Производительность не является критически важной.
- Приложение не оптимизировано под работу с
ValueTask.📍 Навигация: Вакансии • Задачи • Собесы
#лучшее_из_библиотеки_2025
Please open Telegram to view this post
VIEW IN TELEGRAM
❤15
🛠 RabbitMQ плюс MassTransit
Мы уже давали мини гайд по RabbitMQ и MassTransit, и сейчас повторяем его как шпаргалку. Это один из самых прямых способов завести асинхронное общение сервисов в .NET без ручной возни с протоколом и очередями.
Какие инструменты нужны
• RabbitMQ. Брокер сообщений, который позволяет сервисам отправлять и получать сообщения асинхронно, используя очереди.
• MassTransit. Библиотека для .NET, которая предоставляет простой и удобный API для работы с брокерами сообщений.
Как использовать их вместе
1️⃣ Устанавливаем RabbitMQ
RabbitMQ можно развернуть в Docker:
2️⃣ Настраиваем MassTransit
Необходимо зарегистрировать MassTransit и подключить его к RabbitMQ:
Этот код создает подключение к RabbitMQ, которое позволяет сервису отправлять и получать сообщения.
3️⃣ Создаем производителя
Производитель отправляет сообщения в очередь, используя MassTransit:
4️⃣ Создаем потребителя
Потребитель автоматически получает и обрабатывает сообщения из очереди:
💾 Сохраняйте мини-гайд себе, чтобы не потерять
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#лучшее_из_библиотеки_2025
Мы уже давали мини гайд по RabbitMQ и MassTransit, и сейчас повторяем его как шпаргалку. Это один из самых прямых способов завести асинхронное общение сервисов в .NET без ручной возни с протоколом и очередями.
Какие инструменты нужны
• RabbitMQ. Брокер сообщений, который позволяет сервисам отправлять и получать сообщения асинхронно, используя очереди.
• MassTransit. Библиотека для .NET, которая предоставляет простой и удобный API для работы с брокерами сообщений.
Как использовать их вместе
RabbitMQ можно развернуть в Docker:
docker run -d --hostname my-rabbit --name rabbitmq -p 5672:5672 -p 15672:15672 rabbitmq:management
Необходимо зарегистрировать MassTransit и подключить его к RabbitMQ:
builder.Services.AddMassTransit(x =>
{
x.UsingRabbitMq((context, cfg) =>
{
cfg.Host("localhost", "/", h =>
{
h.Username("guest");
h.Password("guest");
});
});
});
Этот код создает подключение к RabbitMQ, которое позволяет сервису отправлять и получать сообщения.
Производитель отправляет сообщения в очередь, используя MassTransit:
public async Task SendMessage(IBus bus, string message)
{
var endpoint = await bus.GetSendEndpoint(new Uri("queue:order-queue"));
await endpoint.Send(new OrderCreated { OrderId = Guid.NewGuid(), Message = message });
}
Потребитель автоматически получает и обрабатывает сообщения из очереди:
public class OrderConsumer : IConsumer<OrderCreated>
{
public Task Consume(ConsumeContext<OrderCreated> context)
{
Console.WriteLine($"Получено сообщение: {context.Message.Message}");
return Task.CompletedTask;
}
}
💾 Сохраняйте мини-гайд себе, чтобы не потерять
📍 Навигация: Вакансии • Задачи • Собесы
#лучшее_из_библиотеки_2025
Please open Telegram to view this post
VIEW IN TELEGRAM
2❤8🤩1🌚1
В C# потоки управляются через класс
Thread из пространства имен System.Threading. Поток проходит несколько этапов на протяжении своего жизненного цикла. Давайте разберём эти этапы.— Unstarted. Не запущен
Поток создан, но ещё не запущен. Он находится в этом состоянии сразу после инициализации объекта
Thread, но до вызова метода Start().Thread thread = new Thread(MyMethod);
// Поток создан, но не запущен
— Running. Выполняется
Поток начинает выполнение после вызова
Start(). В этом состоянии поток выполняет код, переданный в качестве делегата.thread.Start();
// Поток запущен и выполняется
— Waiting. Ожидание
Поток приостанавливается, ожидая выполнения какого-либо условия или ресурса. Это может быть вызвано методами:
•
Thread.Sleep() — поток засыпает на заданное время.•
Monitor.Wait() или lock — поток ожидает захвата монитора.•
Thread.Join() — поток ожидает завершения другого потока.Thread.Sleep(1000);
// Поток приостановлен на 1 секунду
— Blocked. Заблокирован
Поток заблокирован, пытаясь получить доступ к ресурсу, уже занятому другим потоком. Например, ожидание захвата блокировки через
lock.— Stopped. Остановлен
Поток завершает выполнение. Это состояние наступает, когда метод, выполняемый в потоке, завершает работу или вызывается устаревший метод
Abort(). Поток в этом состоянии больше нельзя запустить снова.thread.Join();
// Основной поток ожидает завершения
Дополнительные состояния
— Background. Фоновый поток
Поток может быть фоновым, если свойство
IsBackground установлено в true. Фоновые потоки завершаются автоматически, когда завершается основной поток приложения.thread.IsBackground = true;
// Устанавливаем поток как фоновый
— Suspended. Приостановлен (устарело)
Метод
Suspend() приостанавливал выполнение потока, но был удалён из новых версий .NET из-за возможных проблем с безопасностью.📍 Навигация: Вакансии • Задачи • Собесы
#лучшее_из_библиотеки_2025
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍4
⚙️ Передаём данные между потоками
В C# есть несколько способов передать данные из одного потока в другой. Выбор зависит от требований к производительности, удобству и безопасности. Несколько распространенных вариантов:
1️⃣ Использование BlockingCollection<T>
Это потокобезопасная коллекция, позволяющая передавать данные от одного потока к другому.
2️⃣ Использование TaskCompletionSource<T>
Когда нужно передать значение между потоками в будущем.
3️⃣ Использование ConcurrentQueue<T>
Если нужно неблокирующее хранилище данных.
4️⃣ Использование Channel<T> (System.Threading.Channels)
Альтернативный подход к BlockingCollection<T>
💬 Какой вариант используете в проде?
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека шарписта
#лучшее_из_библиотеки_2025
В C# есть несколько способов передать данные из одного потока в другой. Выбор зависит от требований к производительности, удобству и безопасности. Несколько распространенных вариантов:
Это потокобезопасная коллекция, позволяющая передавать данные от одного потока к другому.
var collection = new BlockingCollection<int>();
// Поток-поставщик (Producer)
Task.Run(() =>
{
for (int i = 0; i < 10; i++)
{
collection.Add(i);
Console.WriteLine($"Производитель: добавил {i}");
Thread.Sleep(500);
}
collection.CompleteAdding();
});
// Поток-потребитель (Consumer)
Task.Run(() =>
{
foreach (var item in collection.GetConsumingEnumerable())
{
Console.WriteLine($"Потребитель: получил {item}");
}
}).Wait();
Когда нужно передать значение между потоками в будущем.
var tcs = new TaskCompletionSource<int>();
// Поток-поставщик
Task.Run(() =>
{
Thread.Sleep(2000);
tcs.SetResult(42);
});
// Поток-потребитель
int result = await tcs.Task;
Console.WriteLine($"Получено: {result}");
Если нужно неблокирующее хранилище данных.
var queue = new ConcurrentQueue<int>();
// Поток-поставщик
Task.Run(() =>
{
for (int i = 0; i < 10; i++)
{
queue.Enqueue(i);
Console.WriteLine($"Добавлено {i}");
Thread.Sleep(500);
}
});
// Поток-потребитель
Task.Run(() =>
{
while (true)
{
if (queue.TryDequeue(out int item))
{
Console.WriteLine($"Получено {item}");
}
Thread.Sleep(100);
}
}).Wait();
Альтернативный подход к BlockingCollection<T>
var channel = Channel.CreateUnbounded<int>();
// Поток-поставщик
_ = Task.Run(async () =>
{
for (int i = 0; i < 10; i++)
{
await channel.Writer.WriteAsync(i);
Console.WriteLine($"Производитель: {i}");
await Task.Delay(500);
}
channel.Writer.Complete();
});
// Поток-потребитель
await foreach (var item in channel.Reader.ReadAllAsync())
{
Console.WriteLine($"Потребитель: {item}");
}
📍 Навигация: Вакансии • Задачи • Собесы
#лучшее_из_библиотеки_2025
Please open Telegram to view this post
VIEW IN TELEGRAM
🤩5❤2
Мы раньше кидали эту команду.
dotnet new gitignore делает все за вас. В ней уже прописаны все типичные исключения: каталоги bin/, obj/, кэш NuGet, файлы публикаций, временные артефакты IDE и прочие служебные данные, которые не должны попадать в репозиторий.Не нужно искать шаблон на GitHub или копировать его вручную — всё доступно из коробки.
📍 Навигация: Вакансии • Задачи • Собесы
#лучшее_из_библиотеки_2025
Please open Telegram to view this post
VIEW IN TELEGRAM
👍29❤1