C# 1001 notes
前往频道在 Telegram
Регулярные короткие заметки по C# и .NET. Просто о сложном для каждого. admin - @haarrp
显示更多6 541
订阅者
-224 小时
+47 天
+330 天
帖子存档
6 541
🚨 «Нет времени на тесты» уже не работает
В 2026 писать тесты стало проще, чем придумывать оправдания
ИИ генерит шаблоны, дописывает кейсы и закрывает рутину
Если у тебя есть нормальная структура, всё остальное ускоряется в разы
Вот минимальный стек, который покрывает почти всё
• Для юнитов
• xUnit остаётся стандартом
• TUnit можно смотреть как более современную альтернативу
Для ассёртов
• Shouldly даёт максимально читаемые проверки
• FluentAssertions теперь платный, это стоит учитывать
Для интеграционных тестов
Aspire сильно упрощает жизнь
WebApplicationFactory плюс TestContainers дают реальные зависимости в тестах
Respawn чистит базу между прогонами
Для фронта
• Playwright сейчас лучший выбор
• Selenium уже больше про легаси
Для моков
• NSubstitute самый чистый по API
• Moq как дефолт, если привык
Для данных
Bogus и AutoFixture закрывают генерацию тестовых сценариев
Для перфома нса
• BenchmarkDtNet для микро-бенчей
• k6 для нагрузки
• NBomber если хочешь остаться в C#
Что по факту важно
Тебе не нужен весь этот стек сразу
Достаточно двигаться по порядку
• Сначала юнит-тесты
• Потом интеграция
• Потом нагрузка
• Потом E2E
Самый частый фейл не в инструментах
А в том, что тесты откладывают «на потом»
В 2026 это уже странное решение
Гайд по интеграционным тестам в Aspire
https://antondevtips.com/blog/dotnet-aspire-integration-testing-best-practices-for-distributed-applications?utm_source=twitter&utm_medium=social&utm_campaign=09-04-2026
6 541
👩💻 Открытый урок «Облегчённые (Slim) примитивы синхронизации»
🗓 16 апреля в 20:00 МСК
🆓 На открытом уроке рассмотрим:
✔ Проблему синхронизации доступа к общему ресурсу в многопоточном приложении в рамках внутрипроцессного взаимодействия;
✔ Разберём классическую задачу читателей–писателей и её реализацию с использованием примитивов синхронизации из пространства имён System.Threading;
✔ Отдельно обсудим, в каких случаях облегчённые версии примитивов (например, SemaphoreSlim и ReaderWriterLockSlim) оказываются эффективнее стандартных решений, таких как Monitor, Mutex и конструкция lock.
Для кого:
Вебинар будет полезен разработчикам, которые уже знакомы с базовыми механизмами синхронизации в .NET и хотят углубить понимание инструментов, предоставляемых стандартной библиотекой для построения безопасных и производительных многопоточных приложений.
🔗 Ссылка на регистрацию: https://otus.pw/ncbR/
6 541
Repost from C# (C Sharp) programming
🚀 Почему этот EF Core код тормозит?
Технически - всё ок.
По производительности не очень.
Вот типичная ошибка:
❌ Загружаешь всю сущность (все колонки)
❌ Потом фильтруешь и мапишь уже в памяти
Что происходит:
- лишние данные тянутся из БД
- растёт нагрузка на сеть
- увеличивается потребление памяти
- замедляется приложение
✅ Как правильно:
Используй проекцию через `.Select()` прямо в запросе:
- берёшь только нужные поля
- меньше данных из БД
- быстрее запрос
- меньше нагрузка на систему
📌 Правило простое:
Не тащи всё - бери только то, что используешь
Именно такие мелочи чаще всего дают x2–x10 к скорости.
6 541
⚡️ Что происходит внутри инфраструктурных сервисов Yandex Cloud?
Разработчики Yandex Cloud и Yandex Infrastructure расскажут об этом на встрече для разработчиков, архитекторов и инженеров, которая пройдет 16 апреля.
В программе вас ждут реальные технические варианты реализации и опыт нетривиальных решений разработчиков платформы:
— Инфраструктура как код для управления оповещениями: и никаких проблем
— Развёртывание в ритме танго: как мы заменили оркестрацию процесса установки «хореографией»
— Как мы оптимизируем вывод больших языковых моделей: кэширование, время отклика и ресурсы графических ускорителей
— Как мы строили собственную сеть доставки контента и через что нам пришлось пройти?
— Как мы работаем с уязвимостями на примере современных аппаратных атак
Также команда расскажет о разработке программных решений, которые устанавливаются в инфраструктуре заказчика, и о том, как в процессе установки оркестрацию заменили «хореографией».
Участники смогут обсудить волнующие вопросы, варианты реализации и ошибки с разработчиками сервисов Yandex Cloud и другими участниками.
Встреча пройдет офлайн в Москве и онлайн. Помимо экспертных докладов, офлайн участников ждут секретная техническая сессия и развлекательная программа, а онлайн-участников ждёт инженерное соревнование в прямом эфире.
Зарегистрируйтесь, чтобы послушать реальные истории от разработчиков, обменяться опытом и узнать, что скрыто под «капотом» инфраструктурных сервисов, а также какие планы у команды на будущее.
6 541
Полезный паттерн для Minimal APIs в .NET, если вы хотите организовать проект по принципу Vertical Slice Architecture.
Идея очень простая.
Вместо того чтобы держать все роуты в
Program.cs, каждый endpoint выносится в отдельный класс.
Создаётся небольшой интерфейс:
public interface IEndpoint
{
void MapEndpoint(IEndpointRouteBuilder app);
}
Дальше каждый endpoint просто реализует этот интерфейс:
public class GetFollowerStats : IEndpoint
{
public void MapEndpoint(IEndpointRouteBuilder app)
{
app.MapGet("users/{userId}/followers/stats", async (
Guid userId,
ISender sender) =>
{
var query = new GetFollowerStatsQuery(userId);
Result<FollowerStatsResponse> result = await sender.Send(query);
return result.Match(Results.Ok, CustomResults.Problem);
})
.WithTags(Tags.Users);
}
}
Что это даёт:
• endpoints изолированы по фичам
• код становится намного чище
• проще масштабировать API
• удобно использовать вместе с CQRS / MediatR
Регистрация таких endpoints занимает буквально пару миллисекунд при старте приложения.
Отличный способ держать Minimal API структурированным даже в больших проектах.6 541
Repost from C# (C Sharp) programming
Vector Search - как это работает (и почему это важно для .NET разработчиков)
Vector search ищет смысловую близость, а не просто точные совпадения.
Он сравнивает данные - текст, изображения или аудио - используя векторные эмбеддинги в многомерном пространстве.
То есть система ищет не одинаковые слова, а похожие по смыслу объекты.
Почему это важно?
Vector search лежит в основе многих AI-функций:
- семантический поиск
- рекомендательные системы
- интеграции с LLM
- умные ассистенты внутри приложений
Добавив векторный поиск в приложение, разработчик может создавать намного более умные продукты, которые понимают смысл запросов пользователя.
Это дает реальную бизнес-ценность - от поиска по документам до персонализированных рекомендаций.
📍 Полный пример реализации
6 541
🔵Ozon Tech приглашает на Community .NET Meetup
24 марта (вторник) в Москве (Лофт Casa Picassa) и онлайн.
В программе три доклада, много кейсов и камерная дискуссия без записи. В фокусе primitive obsession, нагрузка с Load Shedding и Escape Analysis в JIT.
За подробной программой и регистрацией — сюда ⬅️
6 541
⚡️ Языки программирования и их самые любимые фичи
• 🐍 Python - чистый и читаемый синтаксис
• 🖥️ BASIC - очень дружелюбен для новичков
• 📊 Visual Basic - простое создание GUI
• 🟨 JavaScript - запускается везде и сразу
• 🐘 PHP - очень простой деплой веб-приложений
• 💎 Ruby - красивый и элегантный синтаксис
• 🎵 Groovy - бесшовная интеграция с Java
• ☕ Java - огромная экосистема и стабильность
• 🟣 C# - отличные инструменты и IDE
• 🐹 Go - простая и быстрая конкурентность
• 🐦 Swift - современный и безопасный дизайн
• 🅺 Kotlin - встроенная защита от null
• 🎯 Dart - отлично работает с Flutter
• 🧮 Fortran - сверхбыстрые научные вычисления
• 🔧 C - полный контроль над железом
• 🍎 Objective-C - мощная динамическая runtime-система
• 🔺 Scala - сочетание функционального и ООП
• ⚡ Zig - простой и предсказуемый системный код
• 🐪 Perl - невероятно мощная обработка текста
• 🚀 C++ - высокая производительность и контроль
• 🦀 Rust - безопасность памяти без garbage collector
• ⚙️ Assembly - максимальный контроль и производительность
6 541
В .NET 8 появился простой способ сделать HttpClient устойчивым к сбоям — буквально одной строкой.
Microsoft добавила библиотеку Microsoft.Extensions.Http.Resilience, в которой уже есть готовые pipeline’ы для обработки ошибок при HTTP-запросах.
Что это даёт из коробки:
- Retry при временных сбоях
- Timeout
- Circuit Breaker
- Rate limiting
- Защиту от перегрузки
Подключается максимально просто:
services.AddHttpClient<GitHubService>(static httpClient =>
{
httpClient.BaseAddress = new Uri("https://api.github.com/");
})
.AddStandardResilienceHandler();6 541
⚡️ URL shortener за <100 строк на .NET - реально
Идея простая: у тебя есть входной URL -> генеришь короткий код -> сохраняешь в БД -> по коду делаешь редирект.
Что нужно собрать
- Генератор уникального кода
Делай base62 (0-9, a-z, A-Z) длиной 6-8 символов.
Главное - гарантировать уникальность:
- либо проверка в БД и повтор генерации при коллизии
- либо уникальный индекс по Code и ретрай при ошибке сохранения
- База данных
Таблица
ShortenedUrl:
- Id (Guid)
- LongUrl (string)
- Code (string, unique)
- CreatedOnUtc (DateTime)
Опционально:
- ExpiresOnUtc
- Clicks
- CreatedByIp
- 2 эндпоинта (Minimal API)
- POST /shorten
- валидируешь URL (Uri.TryCreate)
- генеришь code
- формируешь shortUrl из scheme + host + code
- сохраняешь в БД
- возвращаешь shortUrl
- GET /{code}
- ищешь code в БД
- если нет - 404
- если есть - Results.Redirect(LongUrl)
Почему чаще всего "падают" такие сервисы
- Коллизии кода -> решается unique index + retry
- Открытый редирект на мусор -> валидируй UriKind.Absolute и при желании режь опасные схемы (только http/https)
- Производительность поиска -> индекс по Code обязателен
- Правильный shortUrl за прокси -> если сервис за nginx/cloudflare, учитывай Forwarded Headers, иначе host/scheme будут неправильными
Если делать максимально чисто - генератор кода отдельным сервисом, модель + DbContext, и два эндпоинта. Это и укладывается в <100 строк.6 541
🚀 LOAD BALANCER ЗА 1 МИНУТУ
Load Balancer - это «диспетчер трафика» между пользователями и серверами.
Когда пользователей становится много, один сервер перестаёт справляться:
- 500 пользователей — работает нормально
- 1 000 — начинает тормозить
- 10 000 — может упасть из-за перегрузки
Load Balancer распределяет входящие запросы между несколькими серверами, чтобы ни один из них не перегружался. Это повышает производительность и позволяет системе обслуживать больше пользователей.
Проблемы без Load Balancer:
- Один сервер = одна точка отказа
- Любой сбой или проблема с сетью — приложение полностью недоступно
- Ограниченная мощность
- При росте нагрузки — медленные ответы и падения
Как работает Load Balancer:
1. Все запросы сначала попадают в Load Balancer
2. Он проверяет, какие серверы работают и доступны
3. Распределяет трафик по серверам на основе:
- текущей нагрузки
- времени ответа
- доступности
4. Если сервер перестаёт отвечать — трафик автоматически перенаправляется на рабочие
В результате:
- нагрузка распределяется равномерно
- используются только «здоровые» серверы
- уменьшаются задержки
- система остаётся стабильной
Зачем нужен Load Balancer:
- Scalability — можно добавлять новые серверы без изменений на стороне клиента
- High Availability — если один сервер падает, система продолжает работать
- Better Performance — запросы обрабатываются быстрее
- Efficient resource usage — равномерное использование ресурсов и отсутствие узких мест
Главная идея:
Load Balancer — основа масштабируемых и отказоустойчивых систем. Без него любое приложение рано или поздно упрётся в предел одного сервера.
Подписывайся, больше фишек каждый день !
// Пример конфигурации Nginx как Load Balancer
http {
upstream backend {
server 192.168.1.10;
server 192.168.1.11;
server 192.168.1.12;
}
server {
listen 80;
location / {
proxy_pass http://backend;
}
}
}6 541
👨💻 Ручная сборка, деплой по инструкции в Confluence и ночные правки на сервере — частая реальность ASP.NET-проектов. Пока система доставки не автоматизирована, скорость разработки и стабильность всегда под угрозой.
На открытом уроке разберём, как выстроить рабочий pipeline от коммита до деплоя. Покажем типовую цепочку: сборка, тесты, упаковка в Docker-образ, публикация в реестр и автоматическое развертывание.
❗️ Вы увидите CI/CD не как абстрактную DevOps-теорию, а как воспроизводимый процесс, который можно применить в собственном проекте. Это фундамент для перехода к микросервисам и контейнерной инфраструктуре без лишней сложности.
🗓 Встречаемся 11 февраля в 20:00 МСК в преддверии старта курса «C# ASP.NET Core-разработчик».
➡️ Регистрация открыта: https://tglink.io/ebe2ec9f037e4d?erid=2W5zFGj7XNQ
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
#реклама
О рекламодателе
6 541
⚡️ Миграция хеширования паролей без поломки логина
Ты сделал маленький и вроде бы аккуратный рефакторинг - и сломал весь логин.
Логику хеширования паролей ты аккуратно вынес в отдельный слой. Отлично.
А потом решил обновиться — заменить PBKDF2 на bcrypt.
Просто поменял реализацию. Казалось бы, безопасно.
Но внезапно:
- старые пользователи больше не могут войти
- пароли перестали совпадать
- аутентификация массово падает
Ты только что внёс breaking change, даже не заметив этого.
Это классическая ловушка в аутентификации — менять алгоритм хеширования без стратегии миграции.
Важно понимать:
- пароли в базе уже захешированы старым алгоритмом
- новый алгоритм не умеет их проверять
- простой swap реализации = мгновенный outage
-
⚡️Правильный подход:
- поддерживать несколько алгоритмов одновременно
- определять алгоритм по формату хеша
- при успешном логине пересохранять пароль новым алгоритмом
- без сброса паролей
- без даунтайма
Маленькие изменения в use case-ах, особенно в аутентификации, могут иметь огромные последствия.
6 541
Есть соглашения по именованию в коде, которые все постоянно нарушают?
Имена классов, слоёв, обработчиков, сервисов - это часть архитектуры.
Но обычно всё держится на:
• договорённостях в голове
• комментариях в Wiki
“ну мы же так решили”
А потом кто-то добавляет UserCmdHandler, DoStuffManager или NewService2 - и структура просто разваливается.
💡 Решение: архитектурные тесты
Вы можете написать тесты, которые проверяют саму архитектуру, а не бизнес-логику.
Например:
• все CommandHandler обязаны заканчиваться на CommandHandler
• классы из Application не должны ссылаться на Infrastructure
• контроллеры не имеют доступа к репозиториям напрямую
DTO не должны жить в доменной модели
И если кто-то нарушил правило - тест падает. Сразу. В CI.
⚙️ Что это даёт
Архитектура перестаёт быть кривой и косой.
Она начинает подчиняться строгим правилам.
Новый разработчик в команде может не знать всех договорённостей, но код всё равно останется чистым, потому что правила защищены тестами.
🧠 Главное осознание
Архитектурные тесты защищают структуру.
А структура - это то, что определяет, станет проект поддерживаемым…
или превратится в хаос через год.
6 541
🖥 Если ты делаешь бэкенд на .NET и хочешь расти не «по туториалам», а в сторону прод-уровня, архитектуры и реальных систем - это золото.
Архитектура и структура проектов
N-Layered vs Clean vs Vertical Slice Architecture
https://antondevtips.com/blog/n-layered-vs-clean-vs-vertical-slice-architecture
Лучшая структура .NET-проектов с Clean Architecture и Vertical Slices
https://antondevtips.com/blog/the-best-way-to-structure-your-dotnet-projects-with-clean-architecture-and-vertical-slices
Зачем писать архитектурные тесты
https://antondevtips.com/blog/why-do-you-need-to-write-architecture-tests-in-dotnet
От модульного монолита к микросервисам
https://antondevtips.com/blog/migrating-modular-monolith-to-microservices-in-dotnet
API и бэкенд-практики
Best Practices для REST API
https://antondevtips.com/blog/best-practices-for-building-rest-apis
90% API не RESTful - что вы упускаете
https://antondevtips.com/blog/90-of-apis-are-not-restful-what-youre-missing-and-when-it-matters
Как ускорить Web API
https://antondevtips.com/blog/how-to-increase-performance-of-web-apis-in-dotnet
Аутентификация и авторизация в ASP.NET Core
https://antondevtips.com/blog/authentication-and-authorization-best-practices-in-aspnetcore
Интеграционные тесты в ASP.NET Core
https://antondevtips.com/blog/asp-net-core-integration-testing-best-practises
EF Core и данные
Почему не нужен Repository поверх EF Core
https://antondevtips.com/blog/why-you-dont-need-a-repository-in-ef-core
5 скрытых NuGet-пакетов для EF Core
https://antondevtips.com/blog/5-hidden-efcore-nuget-packages
Кеширование в .NET
https://antondevtips.com/blog/how-to-implement-caching-strategies-in-dotnet
Resilience, инфраструктура, прод
Retry и устойчивость с Polly и Microsoft Resilience
https://antondevtips.com/blog/how-to-implement-retries-and-resilience-patterns-with-polly-and-microsoft-resilience
Загрузка больших файлов в Azure Blob Storage
https://antondevtips.com/blog/implementing-large-file-uploads-and-downloads-in-azure-blob-storage-with-dotnet
Деплой в Azure с Neon Postgres и .NET Aspire
https://antondevtips.com/blog/how-to-deploy-dotnet-application-to-azure-using-neon-postgres-and-dotnet-aspire
Job Scheduler TickerQ
https://antondevtips.com/blog/tickerq-the-modern-dotnet-job-scheduler-that-beats-quartz-and-hangfire
Observability
Старт с OpenTelemetry, Jaeger и Seq
https://antondevtips.com/blog/getting-started-with-open-telemetry-in-dotnet-with-jaeger-and-seq
Код и язык
Как писать чище и лучше код в .NET
https://antondevtips.com/blog/how-to-write-better-and-cleaner-code-in-dotnet
Новые фичи .NET 10 и C# 14
https://antondevtips.com/blog/new-features-in-dotnet-10-and-csharp-14
Extension Members в C# 14
https://antondevtips.com/blog/extension-members-in-csharp14-changed-how-we-write-code-forever
Практические проекты
Invoice Builder на .NET с IronPDF
https://antondevtips.com/blog/how-to-build-a-production-ready-invoice-builder-in-dotnet-using-ironpdf
Ошибки разработчиков
Top 10 вещей, которые должен делать .NET-разработчик в 2026
https://antondevtips.com/blog/top-10-things-every-dotnet-developer-needs-to-do-in-2026
15 ошибок .NET-разработчиков
https://antondevtips.com/blog/top-15-mistakes-dotnet-developers-make-how-to-avoid-common-pitfalls
15 ошибок при создании Web API
https://antondevtips.com/blog/top-15-mistakes-developers-make-when-creating-web-apis
Это не «почитать на досуге». Это roadmap от уровня “пишу контроллеры” до “проектирую систему, которая живёт в проде годами”.
6 541
⚙️ Вы настраиваете ASP.NET Core «по наитию» и тратите время на поиск, почему приложение ведет себя по-разному в продакшене и локально?
📆 29 января в 20:00 OTUS проводит открытый урок «Конфигурирование приложения ASP.NET Core» в преддверии старта курса «C# ASP.NET Core разработчик».
На занятии разберем, как выстроить прозрачную и управляемую систему настроек: appsettings.json, провайдеры конфигурации, приоритет применения конфигураций, настройки специфичные для среды и шаблон Options для работы с настройками. Вы поймете, как проектировать конфигурации так, чтобы приложения были стабильными и предсказуемыми.
❗️Урок будет полезен разработчикам ASP.NET Core начального и среднего уровня, которые хотят систематизировать знания и работать по индустриальным стандартам.
➡️ Регистрируйтесь на бесплатный урок: https://tglink.io/0180da777d54?erid=2W5zFH1uFyz
🎁 Все участники открытого урока получат скидку на обучение.
#реклама
О рекламодателе
6 541
✔️ C# может прокачать collection expressions: “аргументы при создании коллекции”
Есть прикольное предложение в csharplang: сделать так, чтобы в collection expressions (`[a, b, c]`) можно было передавать аргументы в создание коллекции.
Проблема сейчас:
Postgres-стайл удобный синтаксис уже есть:
List<int> xs = [1, 2, 3];
Но если тебе важно задать, например, capacity (чтобы не было лишних realloc внутри списка), то приходится писать “старым способом”:
var xs = new List<int>(capacity: 32) { 1, 2, 3 };
Предлагаемое решение:
добавить возможность передавать аргументы прямо в collection expression:
List<int> xs = [args(capacity: 32); 1, 2, 3];
То есть:
- args(...) - это аргументы для конструктора / create-метода
- после ; - элементы коллекции
Зачем это нужно:
- можно сохранить суперкороткий синтаксис [ ... ]
- но при этом контролировать создание коллекции (capacity, comparer и т.д.)
- меньше лишних аллокаций → быстрее в hot-path коде
Если фича дойдёт до релиза, это будет реально удобный апгрейд синтаксиса коллекций в C#.
https://github.com/dotnet/csharplang/blob/main/proposals/collection-expression-arguments.md6 541
🖥 Многопоточность в .NET часто сводят к lock. Но в реальных системах этого недостаточно — особенно под нагрузкой, в легаси-коде и распределённых сценариях.
📕 На открытом уроке разберём, какие инструменты действительно есть в .NET и как выбирать подходящий примитив под конкретную задачу. Рассмотрим Monitor, Mutex, Semaphore, а также другие примитивы из System.Threading: ReaderWriterLockSlim, Barrier, ManualResetEventSlim, SpinLock.
❗️ Вы увидите практические примеры, типовые ошибки и узнаете, где блокировки становятся узким местом. Урок будет полезен разработчикам, работающим с высоконагруженными системами и легаси-кодом, а также тимлидам, которые проектируют архитектуру и отвечают за производительность.
📣 Встречаемся 27 января в 20:00 МСК в преддверии старта курса «C# Developer. Professional». Регистрация открыта: https://otus.pw/t6Xj/
6 541
✅ API Input Validation в .NET: почему FluentValidation лучше, чем Data Annotations
Data Annotations отлично подходят для простых правил:
[Required] - ок
[MaxLength(50)] - норм
Но как только тебе нужно что-то “умнее”, начинается боль:
- проверить данные в базе
- валидировать по настройкам из appsettings.json
- вызвать сервис и принять решение динамически
Data Annotations упираются в потолок, потому что Attribute - это статичная штука.
Туда не получится нормально прокинуть зависимости через DI.
И вот здесь FluentValidation реально сияет ✨
Почему:
FluentValidation-валидаторы - это обычные классы, которые регистрируются в DI контейнере.
А значит, внутрь можно инжектить что угодно:
- сервисы
- конфиги
- репозитории
- кэш
- внешние API
Пример:
нужно проверить, что CouponCode валиден через IPricingService?
Просто инжектишь IPricingService в конструктор валидатора и делаешь проверку.
В итоге валидация превращается из “статической проверки полей”
в полноценный слой логики - динамический, умный и расширяемый.
FluentValidation = правильная валидация для реального продакшена.
现已上线!2025 年 Telegram 研究 — 年度关键洞察 
