C# Portal | Программирование
15K subscribers
756 photos
86 videos
19 files
666 links
Присоединяйтесь к нашему каналу и погрузитесь в мир для C#-разработчика

Связь: @devmangx

РКН: https://clck.ru/3FocB6
Download Telegram
#1 ошибка, которую я вижу у .NET-разработчиков — это повсеместное использование null.

Ссылки на null стали причиной множества багов, уязвимостей и сбоев систем.

Вот 4 способа минимизировать использование null в C#:

1. Возвращайте пустое значение из метода

> если возможно, возвращайте пустой список вместо null
> например, используйте Enumerable.Empty<TResult>()

2. Исключайте null с помощью nullable reference types

> представлены в C# 8.0
> заставляют вас явно учитывать возможность null

3. Используйте паттерн Null Object

> объект, реализующий поведение “ничего не делать”
> позволяет избежать проверок на null

4. Используйте оператор null-условия (?.)

> безопасно обращается к свойствам объектов
> если экземпляр равен null, всё выражение вернёт null

Хотите сократить количество сбоев? Попробуйте эти подходы. 👀

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍163
Пример использования паттерна IOptions в ASP dotnet

IOptions<T> обеспечивает безопасность на этапе компиляции и устраняет использование магических строк.

На втором примере эквивалент с использованием IConfiguration вместо IOptions

А ты используешь этот паттерн? 👀

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
7🤯3🔥2
Записи действительно являются неизменяемыми.

Если вы знаете, как их определять.

Если запись объявлена традиционным способом, нет ограничений на использование обычного сеттера, что позволяет изменять объект после инициализации.

Однако, если в записи используется init только для части свойств, то такая запись не является полностью неизменяемой.

Так как же сделать их неизменяемыми?

Используйте позиционные записи.

Такой тип записей компилятор генерирует со свойствами только для инициализации (init-only).

Может показаться, что первый и второй вариант определения идентичны.

Но позвольте развеять это заблуждение.

Первая форма компилируется во вторую, и во втором случае вы можете заменить init на set и тем самым нарушить основную характеристику записей. 🐸

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
3🔥1🥴1
MongoDB теперь нативно доступен на Azure.

Больше никаких "костылей" между сервисами.

Теперь можно:

> Запускать MongoDB Atlas напрямую из Azure Portal
> Интегрироваться с Azure AI, Databricks, OpenAI — в одном потоке
> Получать единый биллинг по всему стеку

Это будущее cloud-native разработки?

Или тесная интеграция с облаком — палка о двух концах для свободы разработчиков?

Полная разбивка: https://fnf.dev/4n1fsLd ✌️

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
3👍3
На небе и на земле только C# достоин почитания 😇

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
36😁14👍2
Сократил время выполнения SQL-запроса с 70 мс до 1 мс.

Без изменений в коде. Без кэширования. Просто добавил filtered index (фильтрованный индекс).

Фильтрованные индексы — одна из самых недооценённых возможностей SQL.

Они позволяют индексировать только подмножество строк, соответствующих определённому условию — идеально подходят для флагов вроде ProcessedAt IS NULL.

Но есть нюанс: если условие выполняется для большинства строк, индекс не даст прироста производительности.

Эта оптимизация дала огромный прирост в одном из проектов.

В статье подробно разбирается реализацию и показывается, как это использовать: читать

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
14
В EF Core 9 улучшена функция ExecuteUpdate

Небольшое, но полезное улучшение.

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

Однако изначально она поддерживала только примитивные типы.

Если нужно было обновить комплексный тип, приходилось вручную перечислять все его свойства… до выхода EF Core 9.

Теперь комплексные типы полностью поддерживаются — больше не нужно делать это вручную 🙂

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍85🔥1
Rider 2025.2 EAP 4 уже тут

Этот билд приносит поддержку SQL-проектов базы данных через встроенный плагин — без доп. настройки:

> Шаблоны SQL-проектов в стиле SDK
> Сравнение схем и публикация проекта
> Импорт из БД, добавление ссылок и другое

Подробнее > jetbrains.com/rider/nextversion 🐸

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🔥5👏2🤔2
Улучшения производительности FrozenDictionary с целочисленными (int) ключами в .NET 10

FrozenDictionary представляют собой коллекции, оптимизированные для чтения (Dictionary и Set), создание которых занимает больше времени, но чтение из них происходит быстрее по сравнению с неизменяемыми (immutable) коллекциями.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
7🔥1
В чём проблема с синглтоном (Singleton) в многопоточности?

Как реализовать потокобезопасный синглтон?

Две нити (потока) могут одновременно проверить, является ли экземпляр null, и обе получат true.

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

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

Как сделать реализацию потокобезопасной?

Один из распространённых способов — использование блокировки (locking), например, с применением double-check locking (двойной проверки).

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

Какое решение лучше?

На мой взгляд, универсального «лучшего» решения нет — всё зависит от конкретной ситуации. Мне нравится и я рекомендую использовать Lazy.

Вот как можно реализовать паттерн Singleton с использованием Lazy:

> Lazy Initialization: Класс Lazy автоматически управляет отложенной инициализацией экземпляра Singleton. Экземпляр создаётся только при первом обращении.

> Потокобезопасность: Lazy обеспечивает создание экземпляра в потокобезопасном режиме, поэтому нет необходимости использовать блокировки или double-check locking вручную.

> Простота и сопровождаемость: Код становится проще и легче поддерживать, так как вся логика синхронизации инкапсулирована внутри Lazy.

Такой подход рекомендуется в современной разработке на C#, поскольку он использует встроенные возможности .NET Framework для безопасной инициализации в многопоточной среде. 🙂

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍135
Внедрение настроек в .NET? Существует три основных интерфейса:

> IOptions: кэшируется на всё время жизни приложения

> IOptionsSnapshot: переоценивается при каждом запросе (scoped)

> IOptionsMonitor: позволяет получать текущее значение и реагировать на изменения

Используйте IOptions для статической конфигурации, IOptionsSnapshot — в веб-приложениях, где конфигурация может меняться между запросами, а IOptionsMonitor — когда нужно отслеживать изменения настроек.

Подробнее о том, как работает паттерн Options и когда какой интерфейс использовать: read

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
9🔥2
EF Core: DbContextOptionsBuilder используется для настройки DbContext, как показано в примере для консольного проекта. Также он может применяться вместе с внедрением зависимостей (dependency injection)

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
4
Ставить точку или не ставить точку в сообщениях об исключениях? 👀

Байкшеддинг (bikeshedding) — большая проблема в нашей сфере.

Что такое "Bikeshedding"?

"Bikeshedding" — это феномен, также известный как закон тривиальности Паркинсона, при котором в организации несоразмерно много внимания уделяется незначительным вопросам. Это часто происходит на встречах: сложные темы быстро проходят без обсуждения (из-за нехватки знаний), а простые и понятные, вроде оформления сообщений об ошибках вызывают долгие споры.

Термин введён в книге Паркинсона "Law of Triviality". В ней описывается вымышленный комитет, обсуждающий проект ядерного реактора. Технические детали реактора одобряются без вопросов, никто не понимает их глубоко. А вот над проектом велосипедного сарая (bike shed) ведутся долгие дебаты: это всем понятно, каждый хочет высказаться.

Вот типичные примеры bikeshedding в разработке ПО — темы, на которые часто тратится непропорционально много времени, хотя они имеют минимальное влияние на результат:

Стиль кода и форматирование

> Tabs vs. spaces (табуляция или пробелы)
> Максимальная длина строки
> Расположение фигурных скобок {}
> Стиль комментариев и выравнивание docstring'ов
> Формат именования переменных (user_id vs userId)

Выборы в UI-дизайне

> Цвет кнопки или текст (“Отправить” vs “Отослать”)
> Пиксельная точность отступов
> Выбор иконки или шрифта
> Как открывать модалку — слайдом или затуханием

Структура проекта / имена файлов


> Где разместить папку utils
> Куда класть services — в Services/ или Domain/
> PascalCase vs kebab-case для файлов

Инструменты и конфигурация

> Что выбрать: ESLint или Prettier (или оба)
> Нужно ли требовать запятую в конце в массиве
> Какой task runner использовать: npm scripts или Gulp

Конвенции тестирования

> Формат имён тестов (*.test.js vs *.spec.js)
> Использовать Moq или NSubstitute
> Хранить тесты рядом с кодом или в папке tests/

Выбор зависимостей (при равной приемлемости)

> Axios или Fetch API
> EF Core или Dapper для CRUD
> Redux или Zustand в простом фронте

Технический педантизм


> Оверинжиниринг мелкой фичи "на будущее"
> Дебаты: функциональный подход или ООП в хелпере
> Внедрение шаблона проектирования там, где он не нужен

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍207😁4
10 «секретных» ключевых слов в C#, которые используют синьоры, но не знают мидлы и джуны

Что это за ключевые слова? 👇

> extension
Новое ключевое слово в C# 14
Позволяет добавлять методы к уже существующим классам без изменения их исходного кода. Идеально подходит для чистого расширения поведения с новыми возможностями.

> await using
Вызывает IAsyncDisposable для асинхронного освобождения ресурсов.

> when (catch)
Фильтрует исключения в блоках catch на основе условий.

> partial
Разделяет определение класса на несколько файлов. Удобно для автогенерируемого кода или логической организации больших классов.

> readonly struct
Определяет неизменяемый тип значения (value type) с поведением сравнения по значению по умолчанию.

> in
Передаёт параметры по ссылке как только для чтения. Избегает лишнего копирования больших структур, повышая производительность без потери безопасности.

> extern
Указывает, что метод реализован вне текущего кода, как правило, в нативной библиотеке (DLL). Позволяет подключать неуправляемые библиотеки.

> volatile
Гарантирует, что значение поля всегда читается из основной памяти — важно в многопоточном коде. Помогает избегать тонких ошибок синхронизации.

> unsafe
Включает использование указателей и арифметику с ними, а также прямую работу с памятью.

> stackalloc
Выделяет память напрямую в стеке, а не в куче. Подходит для краткоживущих, высокопроизводительных сценариев.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
20🤣3👍2🔥1
Хочешь отслеживать изменения в базе данных в реальном времени?

Я реализовал Change Data Capture (CDC) в .NET с использованием Debezium, PostgreSQL и RabbitMQ.

Поток обработки:

> PostgreSQL настроен на генерацию событий об изменениях
> Debezium перехватывает эти изменения
> События публикуются в RabbitMQ
> MassTransit в .NET потребляет и обрабатывает их

Это лишь один из способов реализации архитектуры, основанной на событиях (Event-Driven Architecture).

Если ты проектируешь распределённые системы в .NET — вот полный гайд по созданию event-driven-систем с RabbitMQ

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
11🔥3
Видишь баг?

9 из 10 разработчиков пропускают его. Проверь себя

Проблема:

> ExecuteUpdateAsync и ExecuteDeleteAsync обходят Change Tracker в EF Core
> Если SaveChangesAsync() потом упадёт — обновления в базе не откатятся автоматически

Решение:


Явно оборачивай все такие команды в транзакцию вручную

Мелочь, а последствия могут быть серьёзные 😨

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍123🎉1
5 недооценённых LINQ-методов, которые мгновенно улучшают твой код:

1. Zip — объединяет две последовательности в пары

2. Chunk — разбивает коллекцию на чанки фиксированного размера

3. OfType<T>() — фильтрует элементы по типу

4. DistinctBy — возвращает уникальные элементы по заданному ключу

5. SelectMany — разворачивает вложенные коллекции в плоский список

Бонус, который почти попал в топ:

> SequenceEqual — сравнивает две коллекции на равенство
> Aggregate — накапливает значение с помощью функции (reduce)
> GroupJoin — объединяет по группам (аналог LEFT OUTER JOIN)
> ToLookup — создает коллекцию, похожую на Dictionary, но с множеством значений
> Intersect — возвращает пересечение двух коллекций

LINQ — кладезь полезных методов, если знаешь, где копать 💪

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1412🔥10
Вы правильно внедряете зависимости в контроллеры?

Многие разработчики об этом не знают 👇

В контроллер можно внедрить зависимости двумя способами:
↳ через конструктор
↳ через метод (endpoint)

Вы когда-нибудь работали с перегруженными контроллерами, в конструкторы которых передаётся слишком много зависимостей?

А вызываемый endpoint использует только часть из них.

Это приводит к перерасходу памяти, так как все зависимости из конструктора выделяются в куче при каждом вызове контроллера — даже если они не используются.

Так зачем не внедрять нужные объекты прямо в метод endpoint’а?

Для этого больше не требуется аннотация [FromServices] — как и в Minimal API.

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

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍20🤔3😁1
Визуализатор планов SQL-запросов для Entity Framework

Расширение EFCore.Visualizer для Visual Studio может стать настоящим прорывом.

Оно позволяет разработчикам просматривать план выполнения SQL-запросов напрямую внутри Visual Studio.

А ты уже пробовал? ☺️

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥16👍43
Секреты оптимизации SQL-запросов

Вот 20 проверенных техник, которые я регулярно использую для оптимизации SQL-запросов: 😊

• Грамотно используйте индексы:
Индексируйте критически важные столбцы, используемые в WHERE, JOIN, ORDER BY и GROUP BY.

• Избегайте SELECT *:
Выбирайте только необходимые столбцы, чтобы сократить объём передаваемых данных и время обработки.

• Реализуйте пагинацию корректно:
Используйте OFFSET и FETCH NEXT или пагинацию методом поиска (seek method) для эффективного постраничного вывода.

• Ограничивайте количество строк как можно раньше:
Применяйте фильтрацию на ранних этапах, чтобы максимально сократить размер выборки.

• Избегайте функций в WHERE:
Функции над столбцами блокируют использование индексов — переписывайте условия, используя «сырые» столбцы.

• Упрощайте JOIN:
Минимизируйте количество соединений и избегайте избыточных JOIN-ов.

• Выбирайте правильные типы JOIN:
Используйте INNER JOIN, LEFT JOIN или EXISTS там, где это уместно, чтобы избежать лишней обработки данных.

• Используйте корректные типы данных:
Сопоставляйте типы данных в JOIN и WHERE, чтобы обеспечить эффективное использование индексов.

• Запрашивайте только изменённые данные:
Реализуйте инкрементальную обработку, а не полный повторный запрос таблиц.

• Группируйте операции:
Пакетная вставка, обновление или удаление снижают накладные расходы на транзакции.

• Исключайте избыточные подзапросы:
Используйте JOIN или CTE вместо повторяющихся подзапросов.

• Используйте EXISTS вместо IN:
EXISTS часто работает быстрее, чем IN, особенно на больших объёмах данных.

• Нормализуйте с умом:
Балансируйте между нормализацией и денормализацией в производительно критичных запросах.

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

• Анализируйте планы выполнения:
Регулярно проверяйте execution plan, чтобы находить и устранять ресурсоёмкие операции.

• Избегайте подстановок с начальным %:
LIKE '%abc' не использует индексы эффективно.

• Делайте транзакции короткими:
Сокращайте время выполнения транзакций, чтобы уменьшить блокировки и конфликты.

• Регулярно обновляйте статистику:
Актуальные статистики обеспечивают точное планирование запросов СУБД.

• Используйте подсказки (query hints) с осторожностью:
Применяйте только после тестирования и при необходимости конкретной оптимизации.

• Постоянно отслеживайте и настраивайте:
Регулярно анализируйте производительность запросов и проактивно оптимизируйте медленные запросы.


👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍84