C# 1001 notes
Kanalga Telegram’da o‘tish
Регулярные короткие заметки по C# и .NET. Просто о сложном для каждого. admin - @haarrp
Ko'proq ko'rsatish6 626
Obunachilar
+324 soatlar
+197 kunlar
+4930 kunlar
Postlar arxiv
6 627
📌 UUID v7 - это почти ULID, только нативно в .NET
Раньше в .NET для идентификаторов чаще всего использовали обычный
Guid.NewGuid().
Проблема в том, что классический UUID случайный. Для уникальности это удобно, но для базы данных - не всегда.
Когда значения генерируются хаотично, новые записи вставляются в разные части индекса. Отсюда:
- больше фрагментации
- дороже вставки
- чаще перестраиваются страницы индекса
- хуже поведение на больших таблицах
Поэтому многие разработчики начали использовать ULID.
ULID состоит из двух частей:
- timestamp
- random
За счет timestamp такие ID сортируются по времени, а значит база может вставлять новые записи более последовательно.
Но начиная с .NET 9 появился встроенный вариант:
Guid.CreateVersion7()
UUID v7 тоже содержит временную часть, поэтому лучше подходит для индексируемых ключей, чем полностью случайный UUID.
Главное отличие:
ULID - отдельный формат и часто сторонняя библиотека.
UUID v7 - обычный Guid, который уже поддерживается в .NET.
Для новых проектов это выглядит как более разумный дефолт:
- не Guid.NewGuid()
- не отдельный ULID-пакет
- а Guid.CreateVersion7()
Особенно если Guid используется как primary key в базе.6 627
Что выведет код?
using System;
class Program
{
static void Main()
{
int x = 10;
Console.WriteLine(x++ + ++x);
}
}
Правильный ответ: 22
Почему: выражение считается слева направо. Сначала x++ возвращает 10, но потом увеличивает x до 11. Затем ++x сначала увеличивает x до 12, потом возвращает 12. В итоге 10 + 12 = 22.6 627
🖥 На Stepik обновили курс «C# с нуля до профи»
Представьте: через четыре месяца вы открываете чужой .NET-проект и читаете его как книгу.
IServiceCollection не вызывает ступора.
async Task<IActionResult> пишется на автомате. Вы точно знаете, почему EF Core сгенерировал именно такой SQL - и как переписать запрос, чтобы он летал.
Это не фантазия. Это результат после 16 модулей, в которых каждая концепция объясняется через код и закрепляется практикой.
ООП, SOLID, LINQ, async/await, DI, EF Core, ASP.NET Core, Docker, Kubernetes - всё, что казалось магией, станет рабочим инструментом.
А бонусом - портфолио проектов: от CLI-утилит и REST API до собственного SaaS с multi-tenancy, JWT и деплоем в Kubernetes под TLS.
Скидка - 58% доступна 48 часов: https://stepik.org/a/282984/6 627
🚀 ASP.NET Core в 2026: если не знаешь это - ты отстал
Одна картинка закрывает почти весь стек, который реально нужен в проде. Без воды и устаревших практик.
Сейчас ASP.NET Core уже не про «сделать API», а про систему: от роутинга и DI до очередей, кешей и realtime. Если ты всё ещё пишешь просто контроллеры и думаешь, что этого достаточно - плохие новости.
Что важно:
• основа осталась той же, но усложнился прод
• логирование и мониторинг теперь обязательны
• кеш без стратегии уже не спасает
• без resilience и retry твой сервис падает при первой же проблеме
Отдельно бросается в глаза тренд:
минимум магии, максимум контроля
ручной mapping вместо AutoMapper
явная архитектура вместо «оно само работает»
И ещё момент, который многие игнорят:
• экосистема вокруг стала важнее самого фреймворка
• Redis, Kafka, OpenAPI, gRPC, SignalR - это уже не «дополнительно», это база
Если коротко:
ASP.NET Core сейчас это не про backend
это про сборку полноценной распределённой системы
И вопрос уже не в том, знаешь ли ты .NET
а в том, умеешь ли ты строить сервисы, которые живут под нагрузкой
6 627
⚙️ Почему
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, где сигнатура задаётся самим фреймворком. Там приходится мириться, но даже там стоит ловить исключения локально и логировать их.6 627
🚀 Ты всё ещё называешь обёртку над 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/
6 627
⚙️ Когда Hash Join быстрее Nested Loops
Внутри SQL-движка соединение таблиц — это не магия, а конкретный алгоритм. Сравним два подхода к соединению таблиц.
Nested Loops работает буквально так, как звучит: берём строку из первой таблицы и ищем совпадения во второй. Если вторая таблица имеет подходящий индекс, поиск по нему будет очень быстрым, и такой алгоритм блестяще справляется с задачей маленькое соединяется с большим.
Hash Join подходит там, где Nested Loops захлёбывается. Он сначала строит хэш-таблицу по одной из входных таблиц, а затем пробегается по второй и ищет совпадения через хэш-функцию. Это даёт огромный выигрыш, когда нужно соединить два больших набора данных, и когда индексов для ускорения поиска нет. Цена такого подхода — расход памяти.
В итоге — если речь идёт о маленьком наборе строк против большого и есть индекс, Nested Loops окажется быстрее. Но если обе таблицы крупные и индексы не спасают, Hash Join чаще всего становится оптимальным выбором.
#dotnet_challenge
6 627
👩💻 Приглашаем на открытый урок «Облегчённые (Slim) примитивы синхронизации»
🗓 16 апреля в 20:00 МСК
🆓 На открытом уроке рассмотрим:
✔️ Проблему синхронизации доступа к общему ресурсу в многопоточном приложении в рамках внутрипроцессного взаимодействия;
✔️ Разберём классическую задачу читателей–писателей и её реализацию с использованием примитивов синхронизации из пространства имён System.Threading;
✔️ Отдельно обсудим, в каких случаях облегчённые версии примитивов (например, SemaphoreSlim и ReaderWriterLockSlim) оказываются эффективнее стандартных решений, таких как Monitor, Mutex и конструкция lock.
🌿 Вебинар является частью курса «C# разработчик. Экспертный уровень»
🔗 Ссылка на регистрацию: https://otus.pw/GyYC/?erid=2W5zFGGTxgH
Реклама. ООО "ОТУС ОНЛАЙН-ОБРАЗОВАНИЕ". ИНН 9705100963.
6 627
🔥 Ты не проверишь весь код, если он большой, но нужные инструменты проверят
Невозможно вручную ревьюить каждую строчку. Даже в маленьком проекте что-то ускользает.
Здесь и подключается статический анализ.
Он работает как второй слой контроля прямо во время разработки. Подсвечивает баги, плохие паттерны и потенциальные уязвимости ещё до запуска кода.
В итоге ты ловишь проблемы на раннем этапе, а не после релиза.
Для C# это особенно просто внедряется. Пара настроек и у тебя уже есть автоматический аудит кода без лишней боли.
Если пишешь на C# и не используешь статический анализ, ты реально теряешь быстрые фиксы и чистоту кода.
Начать можно отсюда
6 627
🚨 «Нет времени на тесты» уже не работает
В 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 627
👩💻 Открытый урок «Облегчённые (Slim) примитивы синхронизации»
🗓 16 апреля в 20:00 МСК
🆓 На открытом уроке рассмотрим:
✔ Проблему синхронизации доступа к общему ресурсу в многопоточном приложении в рамках внутрипроцессного взаимодействия;
✔ Разберём классическую задачу читателей–писателей и её реализацию с использованием примитивов синхронизации из пространства имён System.Threading;
✔ Отдельно обсудим, в каких случаях облегчённые версии примитивов (например, SemaphoreSlim и ReaderWriterLockSlim) оказываются эффективнее стандартных решений, таких как Monitor, Mutex и конструкция lock.
Для кого:
Вебинар будет полезен разработчикам, которые уже знакомы с базовыми механизмами синхронизации в .NET и хотят углубить понимание инструментов, предоставляемых стандартной библиотекой для построения безопасных и производительных многопоточных приложений.
🔗 Ссылка на регистрацию: https://otus.pw/ncbR/
6 627
Repost from C# (C Sharp) programming
🚀 Почему этот EF Core код тормозит?
Технически - всё ок.
По производительности не очень.
Вот типичная ошибка:
❌ Загружаешь всю сущность (все колонки)
❌ Потом фильтруешь и мапишь уже в памяти
Что происходит:
- лишние данные тянутся из БД
- растёт нагрузка на сеть
- увеличивается потребление памяти
- замедляется приложение
✅ Как правильно:
Используй проекцию через `.Select()` прямо в запросе:
- берёшь только нужные поля
- меньше данных из БД
- быстрее запрос
- меньше нагрузка на систему
📌 Правило простое:
Не тащи всё - бери только то, что используешь
Именно такие мелочи чаще всего дают x2–x10 к скорости.
6 627
⚡️ Что происходит внутри инфраструктурных сервисов Yandex Cloud?
Разработчики Yandex Cloud и Yandex Infrastructure расскажут об этом на встрече для разработчиков, архитекторов и инженеров, которая пройдет 16 апреля.
В программе вас ждут реальные технические варианты реализации и опыт нетривиальных решений разработчиков платформы:
— Инфраструктура как код для управления оповещениями: и никаких проблем
— Развёртывание в ритме танго: как мы заменили оркестрацию процесса установки «хореографией»
— Как мы оптимизируем вывод больших языковых моделей: кэширование, время отклика и ресурсы графических ускорителей
— Как мы строили собственную сеть доставки контента и через что нам пришлось пройти?
— Как мы работаем с уязвимостями на примере современных аппаратных атак
Также команда расскажет о разработке программных решений, которые устанавливаются в инфраструктуре заказчика, и о том, как в процессе установки оркестрацию заменили «хореографией».
Участники смогут обсудить волнующие вопросы, варианты реализации и ошибки с разработчиками сервисов Yandex Cloud и другими участниками.
Встреча пройдет офлайн в Москве и онлайн. Помимо экспертных докладов, офлайн участников ждут секретная техническая сессия и развлекательная программа, а онлайн-участников ждёт инженерное соревнование в прямом эфире.
Зарегистрируйтесь, чтобы послушать реальные истории от разработчиков, обменяться опытом и узнать, что скрыто под «капотом» инфраструктурных сервисов, а также какие планы у команды на будущее.
6 627
Полезный паттерн для 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 627
Repost from C# (C Sharp) programming
Vector Search - как это работает (и почему это важно для .NET разработчиков)
Vector search ищет смысловую близость, а не просто точные совпадения.
Он сравнивает данные - текст, изображения или аудио - используя векторные эмбеддинги в многомерном пространстве.
То есть система ищет не одинаковые слова, а похожие по смыслу объекты.
Почему это важно?
Vector search лежит в основе многих AI-функций:
- семантический поиск
- рекомендательные системы
- интеграции с LLM
- умные ассистенты внутри приложений
Добавив векторный поиск в приложение, разработчик может создавать намного более умные продукты, которые понимают смысл запросов пользователя.
Это дает реальную бизнес-ценность - от поиска по документам до персонализированных рекомендаций.
📍 Полный пример реализации
6 627
🔵Ozon Tech приглашает на Community .NET Meetup
24 марта (вторник) в Москве (Лофт Casa Picassa) и онлайн.
В программе три доклада, много кейсов и камерная дискуссия без записи. В фокусе primitive obsession, нагрузка с Load Shedding и Escape Analysis в JIT.
За подробной программой и регистрацией — сюда ⬅️
6 627
⚡️ Языки программирования и их самые любимые фичи
• 🐍 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 627
В .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();