C# (C Sharp) programming
18.3K subscribers
933 photos
47 videos
8 files
753 links
По всем вопросам- @haarrp

C# - канал Senior C# разработчика.

@ai_machinelearning_big_data - Machine learning

@itchannels_telegram - 🔥лучшие ит-каналы

@csharp_ci - C# академия

@pythonlbooks- книги📚

Реестр РКН: https://clck.ru/3Fk3kb

#VRHSZ
Download Telegram
В C# 15 появились union types. И это не косметика, это смена подхода к обработке ошибок.

Вы можете явно описать результат как “либо значение, либо ошибка”, прямо на уровне языка.

Без самодельных Result-классов, без лишних обёрток, без попыток использовать исключения там, где они неуместны.

Раньше, ты либо городишь свой Result и работаешь с лишним бойлерплейтом.
Либо тащишь сторонние библиотеки.

Либо кидаешь исключения и теряешь контроль над потоком.

С union types эта проблема решается .

Pattern matching начинает работать так, как и должен. Ты не гадаешь, что вернул метод, а явно разбираешь все варианты.

Код становится проще читать, проще тестировать и сложнее сломать.
This media is not supported in your browser
VIEW IN TELEGRAM
🖥 Unity 6 заходит в эпоху AI-геймдева: ИИ-агент теперь прямо в редакторе

Unity выкатила в открытую бету AI-помощника, который работает не как «чатик сбоку», а как полноценный агент внутри проекта. Он видит контекст сцены, понимает структуру кода и может сам вносить изменения.

Что умеет:

— Plan Mode: разбивает задачу на шаги, пишет код, ищет ошибки и помогает выстроить архитектуру
— Figma-интеграция: можно дать ссылку на макет, а Unity попробует собрать по нему интерфейс
— Генерация ассетов: текстуры, звуки и 3D-объекты можно создавать по текстовому описанию
— Откат изменений: если агент накосячил, правки можно быстро вернуть назад

Для Pro и Enterprise функции уже доступны. В Personal-версии бету можно попробовать через trial.

Геймдев постепенно превращается в работу не только с кодом и сценами, но и с агентами, которые собирают часть проекта по описанию.

А вместе с этим, похоже, нас ждёт новая волна нейрослоп-игр в Steam.

https://unity.com/ru/features/ai?utm_campaign=unity-ai-beta
Please open Telegram to view this post
VIEW IN TELEGRAM
🖥 Курс «Git Pro: от первого коммита до уровня senior» - на Stepik

project_final_v2_FINAL_truly_final - знакомо?

Значит, пора.

Большинство разработчиков знают 5 команд Git и боятся шестую. Коммитят в main, гуглят «how to undo» и копируют папку «на всякий случай».

Это не работа - это выживание.

После курса вы:
— делаете rebase, не задерживая дыхание;
— разбираете конфликт на 200 файлов по алгоритму;
— возвращаете «потерянные навсегда» коммиты за 30 секунд через reflog;
— пишете историю, которую не стыдно показать на code review.
Git Flow, trunk-based, Pull Request, защита веток, CI/CD-хуки — всё, что отличает джуна от senior в командной работе.

Скидка 53%, 48 часов: https://stepik.org/course/284799/
Please open Telegram to view this post
VIEW IN TELEGRAM
Хватит копировать один и тот же unit test

Если тест отличается только входными данными, не нужно плодить десятки одинаковых методов.

В xUnit для этого есть parameterized tests, они же data-driven tests. Вы пишете один тест, а потом прогоняете его на разных наборах данных.

Самый простой вариант - [InlineData(...)], когда параметры можно прямо указать над тестом.

Если данных больше или нужна нормальная типизация, можно вынести их в TheoryData<T> и подключить через [ClassData(typeof(...))].

Смысл простой: меньше копипасты, чище тесты, проще добавлять новые кейсы.

Вместо пяти почти одинаковых тестов - один понятный сценарий и набор входных данных.

Для xUnit это один из тех приемов, который быстро окупается в любом C# проекте.
Одна функция в C однажды положила заметную часть раннего интернета.

В 1988 году в стандартной библиотеке C была функция `gets()`. Она читала ввод пользователя в буфер, но не проверяла его размер. Если данных приходило больше, чем помещалось, они просто начинали затирать соседнюю память.

Именно это использовал Robert Morris в знаменитом Morris Worm. Червь атаковал `fingerd`, переполнял буфер и заставлял систему выполнять чужой код.

Итог: около 6000 машин были заражены за считанные часы. По оценкам того времени, это была примерно десятая часть всего интернета.

Самое безумное здесь не сам червь, а то, насколько маленькой была причина. Один небезопасный вызов. Один буфер без проверки. Одна функция, которую годами использовали как обычный инструмент.

Позже `gets()` признали настолько опасной, что её фактически выкинули из современного C.

Урок простой: в системном программировании безопасность часто ломается не на сложной криптографии, а на банальном «а что будет, если ввод окажется длиннее, чем мы ожидали?»

#history
🖥 На 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/
Please open Telegram to view this post
VIEW IN TELEGRAM
📌 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 в базе.
Please open Telegram to view this post
VIEW IN TELEGRAM
⚡️ Один SQL-запрос выполнялся за 298 мс.

Почти такой же - за 0,66 мс.

Разница в 451 раз из-за одной строки.

Ситуация обычная: cursor pagination, сортировка по date DESC, id DESC, лимит на 1000 записей и composite index по (date, id). На первый взгляд, все должно работать быстро.

Но EXPLAIN ANALYZE показывает другое: Postgres вроде бы использует Index Scan, но после этого выкидывает 900 000 строк через Filter.

То есть индекс есть, но запрос все равно тащит слишком много лишнего.

Проблема в условии:

`date < @date OR (date = @date AND id <= @lastId)`

Для разработчика это выглядит логично: сначала сравниваем дату, потом id.

Но для оптимизатора такой OR плохо ложится на composite index. В итоге база не может сразу пойти по нужному диапазону и вынуждена фильтровать огромный кусок данных.

Правильнее записать условие через tuple comparison:

`(date, id) <= (@date, @lastId)`

Смысл тот же, но для Postgres это уже понятный диапазон по составному индексу.

И результат: 298 мс превращаются в 0,66 мс.

Индекс сам по себе ничего не гарантирует.

Важно не только создать индекс, но и написать запрос так, чтобы оптимизатор реально смог его использовать.
Что выведет на экран этот код:
Anonymous Quiz
42%
1, 2
3%
1, 0
7%
0, 0
15%
0, 2
24%
Код не скомпилируется
9%
🥒
🖥 C# Roadmap: с нуля до профи

Практическое руководство по росту в C#-разработке. Материал собран для тех, кто хочет получить инженерную глубину, а не просто накликать CRUD по туториалам.

Здесь последовательность изучения, лучшие практики, ресурсы и трезвый разбор того, как работать с ИИ-инструментами и оставаться востребованным.

https://github.com/Develp10/Csharp_Roadmap/
Please open Telegram to view this post
VIEW IN TELEGRAM
15 проезный .NET-библиотек, которые используют senior-разработчики

Open-source библиотеки, которые делают код чище, тесты надёжнее, а разработку быстрее.


**HTTP, устойчивость и DI**

**1. Refit**
Превращает REST API в типизированные C# интерфейсы. Меньше boilerplate вокруг HttpClient.
GitHub: https://github.com/reactiveui/refit

2. Polly
Retry, circuit breaker, timeout и resilience-политики для исходящих вызовов.
GitHub: https://github.com/App-vNext/Polly

3. Scrutor
Автосканирование и регистрация сервисов в DI по конвенциям.
GitHub: https://github.com/khellang/Scrutor

Тестирование

4. Bogus
Генератор реалистичных fake-данных для тестов и сидинга.
GitHub: https://github.com/bchavez/Bogus

5. Verify
Snapshot-тесты для .NET: один раз утвердил вывод, дальше ловишь регрессии.
GitHub: https://github.com/VerifyTests/Verify

6. Testcontainers for .NET
Поднимает реальный PostgreSQL, SQL Server, Redis и другие сервисы в Docker для интеграционных тестов.
GitHub: https://github.com/testcontainers/testcontainers-dotnet

API и фоновые задачи

7. FastEndpoints
Быстрые Minimal API по паттерну REPR без раздутых контроллеров.
Сайт: https://fast-endpoints.com
GitHub: https://github.com/FastEndpoints/FastEndpoints

8. TickerQ
Нативный планировщик фоновых задач без Hangfire, Quartz и лишнего оверхеда.
GitHub: https://github.com/Arcenox-co/TickerQ

9. HotChocolate
Мощный GraphQL-сервер для .NET, когда один гибкий endpoint удобнее десятков REST-маршрутов.
Сайт: https://chillicream.com/docs/hotchocolate
GitHub: https://github.com/ChilliCream/graphql-platform

Микросервисы и messaging

10. Dapr
Service discovery, pub/sub и state management для микросервисов без лишней инфраструктурной сантехники.
Сайт: https://dapr.io
GitHub: https://github.com/dapr/dotnet-sdk

11. Wolverine
Mediator и messaging в одном фреймворке. Как MediatR, только шире по возможностям.
Сайт: https://wolverinefx.net
GitHub: https://github.com/JasperFx/wolverine

Утилиты и работа с данными

12. UnitsNet
Безопасная работа с единицами измерения вместо сырых double для температуры, скорости и расстояний.
GitHub: https://github.com/angularsen/UnitsNet

13. Humanizer
Превращает строки, даты, числа и enum-ы в читаемый вид одной строкой кода.
GitHub: https://github.com/Humanizr/Humanizer

14. ImageSharp
Обработка, ресайз и конвертация изображений в .NET. Кросс-платформенно, без GDI+.
Сайт: https://sixlabors.com/products/imagesharp
GitHub: https://github.com/SixLabors/ImageSharp

Архитектура

15. ArchUnitNET
Тесты для архитектурных правил. Нарушения слоёв и Clean Architecture падают прямо в CI.
GitHub: https://github.com/TNG/ArchUnitNET