C# Portal | Программирование
13.3K subscribers
1.28K photos
131 videos
31 files
994 links
Присоединяйтесь к нашему каналу и погрузитесь в мир для C#-разработчика

Сотрудничество, реклама: @devmangx

Менеджер: @Spiral_Yuri

РКН: https://clck.ru/3FocB6
Download Telegram
Я часто слышу, что C# — мусор и что с ним не стоит работать.

Вот почему, на мой взгляд, он лучше, чем считают некоторые:
В backend-разработке и CPU-intensive сценариях C# может быть значительно быстрее интерпретируемых языков и языков с динамической типизацией.

C# превосходит Python по скорости. Python-код обычно выполняется построчно во время работы программы, тогда как C# заранее компилируется, а затем дополнительно оптимизируется во время выполнения. У него очень эффективный runtime.
В CPU-intensive задачах и высоконагруженных backend-системах C# часто превосходит JavaScript и Node.js.

По производительности C# и Java обычно идут примерно на одном уровне.
Сравнение C# и Go неоднозначно. Go отлично подходит для сервисов, но C# предлагает более богатую экосистему, более продвинутые оптимизации runtime и мощные возможности языка.

C++ и Rust обычно быстрее C#, когда в приоритете максимальная производительность и полный контроль над памятью.

Но это лишь часть картины.

Что предлагает C#:
Производительность
Продуктивность разработчика
Строгая типизация
Поддерживаемость кода
Безопасная работа с памятью
Зрелая экосистема

JIT-компиляция оптимизирует участки кода, которые выполняются чаще всего.
Предварительная компиляция позволяет сократить время запуска и потребление памяти.
Сборщик мусора эффективно работает в приложениях с высокой пропускной способностью.
Разработчики могут использовать API вроде Span<T> и pipelines, чтобы уменьшать количество аллокаций и работать ближе к памяти.

Также C# позволяет создавать масштабируемые приложения, способные обрабатывать тысячи одновременных I/O-операций с помощью async и await.

Наконец, C# подходит для разработки самых разных типов приложений:
> ASP.NET Core — для Web API и backend-систем
> облачные сервисы и распределённые приложения
> WPF, WinUI и .NET MAUI — для desktop-приложений
> кроссплатформенные мобильные приложения
> игры на Unity
> background workers, планировщики и системы автоматизации
> AI-приложения и обработка данных с ML.NET

На C# также можно создавать serverless-функции, IoT-решения, CLI-инструменты, приложения реального времени и высокопроизводительные сетевые сервисы.

C# не всегда оказывается самым быстрым языком в каждом бенчмарке.
Но для многих реальных приложений он предлагает одно из лучших сочетаний производительности, продуктивности, инструментов и зрелости экосистемы.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍212🍾2
Поддержка .NET 8 заканчивается через четыре месяца

10 ноября 2026 года Microsoft прекратит поддержку .NET 8, поэтому уже сейчас стоит планировать переход на .NET 10.
.NET 10 относится к LTS-релизам и будет получать обновления до 14 ноября 2028 года.

Одно из главных изменений — заметный прирост производительности ASP.NET Core. По сравнению с .NET 8 он способен обрабатывать на 15% больше запросов в секунду. Для Minimal APIs потребление памяти также снизилось на 93%, что значительно уменьшает общий working set приложения.

Что нового появилось в .NET 10:

C# 14
В язык добавили extension members, присваивание через null-conditional оператор, ключевое слово field, модификаторы параметров в лямбда-выражениях, а также partial-конструкторы и события.

Файловые приложения
Теперь небольшой C#-код можно запускать прямо из одного файла .cs, без создания .sln и .csproj.

ASP.NET Core
Minimal APIs получили встроенную валидацию и поддержку JSON Patch. Также появились Server-Sent Events и поддержка OpenAPI 3.1.

EF Core
Добавлены опциональные complex types, поддержка JSON и структур, операторы LeftJoin и RightJoin, именованные query-фильтры и расширенные возможности ExecuteUpdate.

.NET Aspire
В Aspire 9.5 появился отдельный CLI, поддержка файлового AppHost, визуализатор генеративного ИИ, улучшенная трассировка, интеграция с хостингом OpenAI и поддержка эмуляторов Azure.

Blazor
Для Blazor WebAssembly добавили Hot Reload, настройку окружения, профилирование производительности и диагностические счётчики. Также улучшили роутинг, предварительную загрузку статических ресурсов и валидацию форм.

Библиотеки и Runtime
Появились новые API для криптографии, сериализации, коллекций, диагностики, числовых операций и работы с ZIP-файлами. Runtime получил улучшения JIT, NativeAOT, девиртуализации методов, стековых аллокаций и генерации кода, а также поддержку AVX10.2.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
2🍾1
Большинство разработчиков неправильно подходят к оптимизации SQL-запросов

Часто разработчики часами переставляют условия в WHERE, переписывают IN на EXISTS или добавляют query hints. Но в большинстве случаев это почти не влияет на производительность.

Современные СУБД и так умеют самостоятельно менять порядок JOIN и применять фильтры как можно раньше. Поэтому важнее не то, как именно записан запрос, а может ли база эффективно использовать индексы и правильно оценить объём данных.

Основной прирост скорости обычно дают три вещи.

Во-первых, фильтры должны позволять использовать индекс.
Например, если применить функцию к индексируемому столбцу:
EXTRACT(YEAR FROM order_date) = 2025
база может отказаться от использования индекса. Гораздо эффективнее задать диапазон по самому столбцу с датой.

Во-вторых, нужно правильно подбирать индексы.
В первую очередь стоит индексировать столбцы, которые участвуют в WHERE, JOIN и ORDER BY. При этом один составной индекс, например (status, order_date), часто работает лучше двух отдельных.

В-третьих, статистика таблиц должна быть актуальной.
Планировщик выбирает план выполнения на основе статистики. Если она устарела, база может выбрать неудачный план даже при хороших индексах.

Поэтому важнее правильно настроить индексы и статистику, чем бесконечно переписывать сам запрос.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
4👍1👏1🍾1
Чувак рассказывает, как провалил техническое интервью из-за оптимизации одного отчётного запроса.
На маленьком объёме данных всё выглядело нормально: запрос выполнялся быстро. Но на тестовой базе с 500 000 строк он внезапно стал очень медленным.

Причина — скрытая проблема N+1: внутри SELECT был подзапрос, который выполнялся заново для каждой строки результата. То есть вместо одного обращения к базе происходили сотни тысяч повторных операций.

Решение оказалось простым — заменить такие подзапросы на JOIN, чтобы база могла обработать данные одним проходом.

Ещё одна частая ошибка — несколько одинаковых подзапросов для расчёта разных метрик. Например, отдельно считать сумму покупок клиента и количество заказов. Вместо этого лучше один раз собрать агрегированные данные через CTE, а потом присоединить результат.

Главный вывод: SQL, который летает на сотне строк, может полностью сломаться на больших данных. Оптимизацию нужно проверять не только на локальных тестах, но и на реальных объёмах.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🤣6👍4🤯1🍾1
В .NET долгое время одним из самых удобных инструментов для организации CQRS и разделения логики был MediatR, он помогал структурировать команды и запросы, разгружал API слой и снижал связанность кода. Многие проекты, особенно с архитектурой Vertical Slice, держались на нём годами.

Но в работе со сложными сценариями у MediatR есть нюанс. Из-за отвязки команд и обработчиков навигация по коду и отладка становятся менее очевидными, особенно когда один обработчик начинает вызывать другой.

Альтернатива, которая решает эти проблемы, — переход на простые ручные обработчики. Такой подход убирает лишнюю рефлексию и декораторы, упрощает трассировку, а IDE быстрее находит нужный участок кода.

Вот гайд как выстроить систему, где:

> Стартовая реализация использует MediatR, а затем заменяется на ручные обработчики

> Регистрация обработчиков происходит автоматически

> Уведомления обрабатываются без MediatR Notifications

> Общая функциональность (логирование, валидация, транзакции) подключается без лишней обвязки

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

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
5🤨1🍾1
В C# 16 разработчики планируют сосредоточиться на нескольких крупных направлениях:

Среди них — развитие unsafe, новый синтаксис для словарей, закрытые enum, улучшенный вывод типов и более удобное декларативное создание интерфейсов.

https://github.com/dotnet/csharplang/discussions/10276/

Как вам такой набор изменений?

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🍾4🌭2
Сегодня у меня для вас небольшая задачка.

Оба метода удаляют один товар и возвращают одинаковые HTTP-статусы, но…

Под капотом они работают совершенно по-разному.

Какую реализацию выбрали бы вы?

Сможете определить различия?

Пишите свои варианты решения в комментариях!

Приятного брейншторма! 🧠

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🍾21
Строки в C# кажутся простой темой — пока не становятся причиной:

нечитаемого кода
лишних аллокаций
скрытых ошибок при сравнении
некорректной валидации
неудобного форматирования многострочного текста

В своих проектах я придерживаюсь пяти правил:
1. Использую интерполяцию строк
2. Для большого количества конкатенаций применяю StringBuilder
3. Проверяю строки через string.IsNullOrWhiteSpace
4. Явно указываю StringComparison
5. Использую raw- или verbatim-строки

Меньше экранирования.
Меньше лишнего шума.
Более читаемый код.
Даже небольшие улучшения в работе со строками делают код безопаснее, чище и проще в поддержке.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
4🍌1😐1🍾1
Паттерн Saga — одна из базовых вещей, которую стоит понимать при работе с распределёнными системами.

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

Обычно Saga строится одним из двух способов:

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

Но самое важное начинается не на happy path, а при сбоях. Для каждого шага нужно заранее продумать, что делать, если он завершится ошибкой: откатить предыдущие действия, запустить компенсирующую операцию или выбрать другой сценарий.

И здесь нет универсального ответа — решение зависит от логики конкретного бизнеса.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👌3🍾1
Вот 8 простых приёмов, которые делают код чище:

Используйте result objects
Объединяйте if, когда условия можно выразить вместе
Применяйте early return
Заменяйте magic strings на enum
Предпочитайте собственные исключения
Используйте LINQ, когда он делает код короче и понятнее
Заменяйте magic numbers на константы
Выносите сложные булевы выражения в отдельные методы

Хороший разработчик часто замечает code smells с первого взгляда.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
5🍾2
Команде .NET стоит внимательнее относиться к документации, потому что многие воспринимают примеры из неё как рекомендуемые практики.

Вот антипример: не стоит добавлять к IEnumerable индексатор, который внутри вызывает ElementAt.

От индексатора обычно ожидают стоимость доступа O(1).

доки

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🍾3
Как обычно рисуют архитектурные диаграммы?

Самый распространённый вариант — UML-диаграммы.
Но есть и другой подход — модель C4.

C4 расшифровывается как:
Context Diagram — диаграмма контекста системы
Container Diagram — диаграмма контейнеров
Component Diagram — диаграмма компонентов
Code Diagram — диаграмма кода

Это лёгкая модель для описания архитектуры, которая помогает постепенно раскрывать систему: от общего представления до деталей реализации.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1🍾1
Windows 11 26H2: что нового этой осенью

Осенью Microsoft выпустит обновление Windows 11 26H2, которое принесёт множество улучшений во всей операционной системе.

Среди изменений — доработки меню «Пуск», изменения панели задач, более глубокие обновления поиска, улучшения Проводника и новые инструменты для повышения удобства работы.

Похоже, это будет один из самых интересных релизов Windows за последние годы.

Вот всё, что известно на данный момент

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🤣51🔥1🍾1
Если тебе кажется, что для результатов true/false есть только if/else
…то вот альтернатива.

Тернарный оператор — это условный оператор в C#, который во многих случаях работает как компактная версия if/else.

Для него нужны три части:
- условие;
- результат, если условие истинно;
- результат, если условие ложно.

Если условие возвращает true, используется первое значение. Если false — второе.
Тернарный оператор поддерживает target-typing и может использоваться с var.

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

Тернарный оператор помогает сократить несколько строк кода до одной.
Но если условий становится много, код быстро становится запутанным и хуже читается.
Так что держи в голове: тернарный оператор — хорошая альтернатива для простых if/else.
Для более сложной логики лучше использовать switch expression.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🤣10😁3🤯2🍾2👏1
Планировщик запросов PostgreSQL использует динамическое программирование, чтобы подобрать наиболее дешёвый порядок JOIN при объединении нескольких таблиц.

Пожалуй, один из тех редких моментов, когда dynamic programming встречается не в задачке с LeetCode, а внутри системы, которой разработчики пользуются каждый день.

https://internals-for-interns.com/posts/postgres-query-planner/

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥41🍾1
Одна из частых проблем в коде — использование чисел без понятного смысла.

Такие значения ничего не объясняют сами по себе, поэтому код становится сложнее читать, понимать и поддерживать, а вероятность ошибок растёт.

Исправить это довольно просто: вынести значение в именованную константу.

Небольшое изменение, которое делает код чище и понятнее.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12❤‍🔥3🍾2👌1
Как понять, что твоя стратегия кеширования правильная?

Ключевая метрика — процент запросов, когда данные находятся в кеше.

Это называется коэффициент попаданий в кеш и показывает, как часто ты можешь переиспользовать закешированный объект.

Вот как замаксить этот коэффициент:

I. Размер пространства ключей

Единственный способ найти элемент в кеше — точно совпасть по ключу.
Чем меньше возможных ключей, тем эффективнее кеш.
Всегда думай, как уменьшить количество возможных ключей.

II. Размер кеша и элементов

Сколько объектов ты можешь хранить в кеше, зависит от их среднего размера и размера самого кеша.
Когда кеш заполнен, приходится вытеснять старые элементы перед добавлением новых.
Это снижает коэффициент попаданий, потому что элементы удаляются даже если могли бы удовлетворить будущие запросы.
Значит, чем больше элементов помещается в кеш, тем выше будет коэффициент попаданий.

III. Долговечность


Во многих случаях можно кешировать объекты на предопределённое время, так называемый Time to Live, TTL.
В других случаях ты не можешь рисковать устаревшими данными и должен инвалидировать объекты в кеше.
В общем, чем дольше ты можешь держать элементы в кеше, тем выше шанс их переиспользовать.

Большинство кейсов, хорошо подходящих для кеширования, имеют высокий ratio чтений к записям.
Потому что закешированные элементы можно создать один раз и хранить длительное время, пока они не истекут или не станут невалидными.

С другой стороны, кейсы с частыми изменениями данных могут сделать кеш бесполезным, потому что элементы успевают устареть до следующего использования.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🍾1
Как быстро находить узкие места в запросах EF Core:

Можно визуализировать план выполнения SQL-запроса прямо в Visual Studio и сразу увидеть, что именно стоит оптимизировать.

Для этого есть расширение EFCore.Visualizer.

Оно поддерживает SQL Server, PostgreSQL, SQLite, MySQL и Oracle.

Используется прямо во время отладки: наведите курсор на запрос EF Core — появится возможность открыть его план выполнения.

Пример на скриншоте .

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🍾4
Что вам не нужно на старте проекта:

— Kubernetes
— микросервисы
— отдельные базы для чтения и записи

Что действительно нужно:

— юнит-тесты
— CI/CD-пайплайн
— монолитная архитектура

Главный враг любого программного проекта — не нехватка времени, а недостаток простоты. Хотя, конечно, Kubernetes для трёх пользователей звучит гораздо солиднее. 😔

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
💯112👍2🍾1
Надоело раскладывать проект по слоям?

Vertical Slice Architecture предлагает другой подход: код группируется по фичам, а не по горизонтальным слоям вроде Controllers, Services и Repositories.

В результате всё, что относится к конкретной фиче, находится рядом:

— выше связность кода
— проще вносить изменения
— меньше переходов между слоями и папками
— бизнес-логика не размазана по всему проекту

И есть ещё один актуальный плюс: такой подход хорошо ложится на работу с LLM и кодинг-агентами. Когда весь контекст фичи собран в одном месте, модели проще понять, что именно нужно изменить.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🍾2🤨1
Используете ли вы человекочитаемые ID объектов?

Разберёмся, почему такой подход стоит применять в приложениях.

Начнём с выбора типа данных для идентификаторов объектов, или первичных ключей.

В реляционных базах данных часто используют целые числа: база автоматически присваивает каждой новой строке следующий порядковый номер. Это простое решение, которое хорошо подходит для небольших систем.

Однако у автоинкрементных ID есть недостаток: они делают приложение уязвимым для перебора идентификаторов. Если ID текущего объекта — 42, злоумышленник может предположить, что следующий объект имеет ID 43. При наличии незащищённых API-эндпоинтов этим можно воспользоваться.

UUID устраняют эту проблему благодаря случайной генерации. Кроме того, они удобны в распределённых системах, поскольку снижают риск коллизий.

UUID также полезны, когда ID объекта необходимо сгенерировать непосредственно в коде, а не на стороне базы данных.

Но какой бы тип данных вы ни выбрали, остаётся один недостаток: сам идентификатор ничего не сообщает об объекте, которому он принадлежит.

Иначе обстоит дело с такими ID:

* ord_01HZW2RKF63AWC1BT901FPGRGT

* tr_afdf5738-6a8e-4d1a-90db-e894a3828320

По префиксу можно понять, к какому типу относится объект. Например, ord может означать Order — заказ, а trTransaction — транзакцию.

При этом такие ID необязательно делать первичными ключами в базе данных. Их можно генерировать в коде перед возвратом данных клиенту.

Такой формат сделает API более удобным и понятным для его потребителей.

Как вы относитесь к человекочитаемым ID объектов?

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🍾1