fa
Feedback
C# 1001 notes

C# 1001 notes

رفتن به کانال در Telegram

Регулярные короткие заметки по C# и .NET. Просто о сложном для каждого. admin - @haarrp

نمایش بیشتر
6 608
مشترکین
+324 ساعت
+527 روز
+4030 روز
آرشیو پست ها

🚀 ASP.NET Core в 2026: если не знаешь это - ты отстал Одна картинка закрывает почти весь стек, который реально нужен в проде
🚀 ASP.NET Core в 2026: если не знаешь это - ты отстал Одна картинка закрывает почти весь стек, который реально нужен в проде. Без воды и устаревших практик. Сейчас ASP.NET Core уже не про «сделать API», а про систему: от роутинга и DI до очередей, кешей и realtime. Если ты всё ещё пишешь просто контроллеры и думаешь, что этого достаточно - плохие новости. Что важно: • основа осталась той же, но усложнился прод • логирование и мониторинг теперь обязательны • кеш без стратегии уже не спасает • без resilience и retry твой сервис падает при первой же проблеме Отдельно бросается в глаза тренд: минимум магии, максимум контроля ручной mapping вместо AutoMapper явная архитектура вместо «оно само работает» И ещё момент, который многие игнорят: • экосистема вокруг стала важнее самого фреймворка • Redis, Kafka, OpenAPI, gRPC, SignalR - это уже не «дополнительно», это база Если коротко: ASP.NET Core сейчас это не про backend это про сборку полноценной распределённой системы И вопрос уже не в том, знаешь ли ты .NET а в том, умеешь ли ты строить сервисы, которые живут под нагрузкой

⚙️ Почему async void ломает ваш код В C# у async void есть дурная репутация, и не зря. Такой метод не возвращает Task, а значит, его нельзя await-ить, нельзя встроить в пайплайн и невозможно корректно отследить завершение. Исключения из него не ловятся обычным образом — они пробиваются в синхронизационный контекст или в пул потоков, где легко превращаются в необработанные и могут уронить процесс.

// Контроллер ASP.NET Core
[HttpPost]
public async void Create() { await _svc.DoAsync(); } // Исключения мимо pipeline

// Библиотека
public async void SaveAsync(Item item) { await _repo.Save(item); } // Вызывающему не сконтролировать
Правильно — всегда возвращать Task:

[HttpPost]
public async Task<IActionResult> Create() { await _svc.DoAsync(); return Ok(); }

public Task Invoke(HttpContext ctx) => _next(ctx);

public Task SaveAsync(Item item) => _repo.Save(item);
Единственный сценарий, где async void уместен, — обработчики событий в UI-фреймворках вроде WPF или WinForms, где сигнатура задаётся самим фреймворком. Там приходится мириться, но даже там стоит ловить исключения локально и логировать их.

🚀 Ты всё ещё называешь обёртку над ChatGPT «AI-продуктом»? Пока ты пишешь промпты - рынок уже ушёл дальше. Сейчас выигрывают
🚀 Ты всё ещё называешь обёртку над ChatGPT «AI-продуктом»? Пока ты пишешь промпты - рынок уже ушёл дальше. Сейчас выигрывают не те, кто умеет красиво формулировать запросы, а те, кто строит агентные системы: - принимают решения сами - ходят в API - работают с Postgres и Redis - управляют браузером через Playwright - доводят задачи до результата без человека И вот правда, о которой мало говорят: 90% таких систем умирают между ноутбуком и продом. Работает локально. Ломается в реальности. Нет архитектуры. Нет устойчивости. Нет деплоя. AI Agents Engineering - курс со Stepik, который закрывает этот разрыв. - LangGraph, AutoGen, Computer Use - архитектура агентов, а не «скрипты на коленке» - LLMOps, логирование, стабильность - деплой в Docker и работа в проде 8 модулей, 120+ шагов, всё через практику. На выходе не «сертификат ради галочки», а: - рабочий production-агент - понимание, как строить такие системы с нуля - навыки, за которые уже платят Сейчас самое окно входа. Через полгода это станет базой, а не преимуществом. Скидка 55% действует ещё 48 часов: https://stepik.org/a/276971/

⚙️ Когда Hash Join быстрее Nested Loops Внутри SQL-движка соединение таблиц — это не магия, а конкретный алгоритм. Сравним два подхода к соединению таблиц. Nested Loops работает буквально так, как звучит: берём строку из первой таблицы и ищем совпадения во второй. Если вторая таблица имеет подходящий индекс, поиск по нему будет очень быстрым, и такой алгоритм блестяще справляется с задачей маленькое соединяется с большим. Hash Join подходит там, где Nested Loops захлёбывается. Он сначала строит хэш-таблицу по одной из входных таблиц, а затем пробегается по второй и ищет совпадения через хэш-функцию. Это даёт огромный выигрыш, когда нужно соединить два больших набора данных, и когда индексов для ускорения поиска нет. Цена такого подхода — расход памяти. В итоге — если речь идёт о маленьком наборе строк против большого и есть индекс, Nested Loops окажется быстрее. Но если обе таблицы крупные и индексы не спасают, Hash Join чаще всего становится оптимальным выбором. #dotnet_challenge

👩‍💻 Приглашаем на открытый урок «Облегчённые (Slim) примитивы синхронизации» 🗓 16 апреля в 20:00 МСК 🆓 На открытом уроке
👩‍💻 Приглашаем на открытый урок «Облегчённые (Slim) примитивы синхронизации» 🗓 16 апреля в 20:00 МСК 🆓 На открытом уроке рассмотрим: ✔️ Проблему синхронизации доступа к общему ресурсу в многопоточном приложении в рамках внутрипроцессного взаимодействия; ✔️ Разберём классическую задачу читателей–писателей и её реализацию с использованием примитивов синхронизации из пространства имён System.Threading; ✔️ Отдельно обсудим, в каких случаях облегчённые версии примитивов (например, SemaphoreSlim и ReaderWriterLockSlim) оказываются эффективнее стандартных решений, таких как Monitor, Mutex и конструкция lock. 🌿 Вебинар является частью курса «C# разработчик. Экспертный уровень» 🔗 Ссылка на регистрацию: https://otus.pw/GyYC/?erid=2W5zFGGTxgH Реклама. ООО "ОТУС ОНЛАЙН-ОБРАЗОВАНИЕ". ИНН 9705100963.

🔥 Ты не проверишь весь код, если он большой, но нужные инструменты проверят Невозможно вручную ревьюить каждую строчку. Даже
🔥 Ты не проверишь весь код, если он большой, но нужные инструменты проверят Невозможно вручную ревьюить каждую строчку. Даже в маленьком проекте что-то ускользает. Здесь и подключается статический анализ. Он работает как второй слой контроля прямо во время разработки. Подсвечивает баги, плохие паттерны и потенциальные уязвимости ещё до запуска кода. В итоге ты ловишь проблемы на раннем этапе, а не после релиза. Для C# это особенно просто внедряется. Пара настроек и у тебя уже есть автоматический аудит кода без лишней боли. Если пишешь на C# и не используешь статический анализ, ты реально теряешь быстрые фиксы и чистоту кода. Начать можно отсюда

🚨 «Нет времени на тесты» уже не работает В 2026 писать тесты стало проще, чем придумывать оправдания ИИ генерит шаблоны, доп
🚨 «Нет времени на тесты» уже не работает В 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

👩‍💻 Открытый урок «Облегчённые (Slim) примитивы синхронизации» 🗓 16 апреля в 20:00 МСК 🆓 На открытом уроке рассмотрим: ✔
👩‍💻 Открытый урок «Облегчённые (Slim) примитивы синхронизации» 🗓 16 апреля в 20:00 МСК 🆓 На открытом уроке рассмотрим: ✔ Проблему синхронизации доступа к общему ресурсу в многопоточном приложении в рамках внутрипроцессного взаимодействия; ✔ Разберём классическую задачу читателей–писателей и её реализацию с использованием примитивов синхронизации из пространства имён System.Threading; ✔ Отдельно обсудим, в каких случаях облегчённые версии примитивов (например, SemaphoreSlim и ReaderWriterLockSlim) оказываются эффективнее стандартных решений, таких как Monitor, Mutex и конструкция lock. Для кого: Вебинар будет полезен разработчикам, которые уже знакомы с базовыми механизмами синхронизации в .NET и хотят углубить понимание инструментов, предоставляемых стандартной библиотекой для построения безопасных и производительных многопоточных приложений. 🔗 Ссылка на регистрацию: https://otus.pw/ncbR/

🚀 Почему этот EF Core код тормозит? Технически - всё ок. По производительности не очень. Вот типичная ошибка: ❌ Загружаешь в
🚀 Почему этот EF Core код тормозит? Технически - всё ок. По производительности не очень. Вот типичная ошибка: ❌ Загружаешь всю сущность (все колонки) ❌ Потом фильтруешь и мапишь уже в памяти Что происходит: - лишние данные тянутся из БД - растёт нагрузка на сеть - увеличивается потребление памяти - замедляется приложение ✅ Как правильно: Используй проекцию через `.Select()` прямо в запросе: - берёшь только нужные поля - меньше данных из БД - быстрее запрос - меньше нагрузка на систему 📌 Правило простое: Не тащи всё - бери только то, что используешь Именно такие мелочи чаще всего дают x2–x10 к скорости.

⚡️ Что происходит внутри инфраструктурных сервисов Yandex Cloud? Разработчики Yandex Cloud и Yandex Infrastructure расскажут
⚡️ Что происходит внутри инфраструктурных сервисов Yandex Cloud? Разработчики Yandex Cloud и Yandex Infrastructure расскажут об этом на встрече для разработчиков, архитекторов и инженеров, которая пройдет 16 апреля. В программе вас ждут реальные технические варианты реализации и опыт нетривиальных решений разработчиков платформы: — Инфраструктура как код для управления оповещениями: и никаких проблем — Развёртывание в ритме танго: как мы заменили оркестрацию процесса установки «хореографией» — Как мы оптимизируем вывод больших языковых моделей: кэширование, время отклика и ресурсы графических ускорителей — Как мы строили собственную сеть доставки контента и через что нам пришлось пройти? — Как мы работаем с уязвимостями на примере современных аппаратных атак Также команда расскажет о разработке программных решений, которые устанавливаются в инфраструктуре заказчика, и о том, как в процессе установки оркестрацию заменили «хореографией». Участники смогут обсудить волнующие вопросы, варианты реализации и ошибки с разработчиками сервисов Yandex Cloud и другими участниками. Встреча пройдет офлайн в Москве и онлайн. Помимо экспертных докладов, офлайн участников ждут секретная техническая сессия и развлекательная программа, а онлайн-участников ждёт инженерное соревнование в прямом эфире. Зарегистрируйтесь, чтобы послушать реальные истории от разработчиков, обменяться опытом и узнать, что скрыто под «капотом» инфраструктурных сервисов, а также какие планы у команды на будущее.

Полезный паттерн для Minimal APIs в .NET, если вы хотите организовать проект по принципу Vertical Slice Architecture. Идея оч
Полезный паттерн для 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 структурированным даже в больших проектах.

Vector Search - как это работает (и почему это важно для .NET разработчиков) Vector search ищет смысловую близость, а не прос
Vector Search - как это работает (и почему это важно для .NET разработчиков) Vector search ищет смысловую близость, а не просто точные совпадения. Он сравнивает данные - текст, изображения или аудио - используя векторные эмбеддинги в многомерном пространстве. То есть система ищет не одинаковые слова, а похожие по смыслу объекты. Почему это важно? Vector search лежит в основе многих AI-функций: - семантический поиск - рекомендательные системы - интеграции с LLM - умные ассистенты внутри приложений Добавив векторный поиск в приложение, разработчик может создавать намного более умные продукты, которые понимают смысл запросов пользователя. Это дает реальную бизнес-ценность - от поиска по документам до персонализированных рекомендаций. 📍 Полный пример реализации

🔵Ozon Tech приглашает на Community .NET Meetup 24 марта (вторник) в Москве (Лофт Casa Picassa) и онлайн. В программе три док
🔵Ozon Tech приглашает на Community .NET Meetup 24 марта (вторник) в Москве (Лофт Casa Picassa) и онлайн. В программе три доклада, много кейсов и камерная дискуссия без записи. В фокусе primitive obsession, нагрузка с Load Shedding и Escape Analysis в JIT. За подробной программой и регистрацией — сюда ⬅️

⚡️ Языки программирования и их самые любимые фичи • 🐍 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 - максимальный контроль и производительность

Нам и так нормально.
Нам и так нормально.

В .NET 8 появился простой способ сделать HttpClient устойчивым к сбоям — буквально одной строкой. Microsoft добавила библиоте
В .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();

⚡️ URL shortener за &lt;100 строк на .NET - реально Идея простая: у тебя есть входной URL -&gt; генеришь короткий код -&gt; с
⚡️ 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 строк.

🚀 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;
        }
    }
}

👨‍💻 Ручная сборка, деплой по инструкции в 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 #реклама О рекламодателе