Lazy Loading по умолчанию выключен в Entity Framework (Core), так что тебе реально нужно целенаправленно включать и искать вот этот вариант N+1 ⬇️
👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🥴3
Делегаты без накладных расходов в .NET 10
JIT в .NET 10 в некоторых случаях может полностью убрать стоимость абстракции при использовании делегатов.
👉 @KodBlog
JIT в .NET 10 в некоторых случаях может полностью убрать стоимость абстракции при использовании делегатов.
Enumerable.Any может быть таким же эффективным, как вручную написанный цикл, который достает Span из ListPlease open Telegram to view this post
VIEW IN TELEGRAM
🔥7❤1
Новый
И ты будешь им пользоваться. Звучит стремно, да?
Но тут другая история.
Официально продвигаемое предложение для C# 15 добавляет labeled
Это решает проблему, на которую все натыкаются в вложенных циклах.
И обычно мы решаем ее криво:
- Используем
- Заводим флаги, которые “протекают” состоянием и прячут намерение.
Оба варианта делают код хуже для чтения и поддержки.
А теперь представь так:
→ Ты задаешь имя циклу, из которого хочешь выйти.
→ Потом пишешь ровно то, что имеешь в виду.
“Выйти из внешнего цикла.”
“Продолжить внешний цикл.”
И да, в других языках это уже есть:
→ Java, Kotlin, Rust, Go, Swift.
C# наконец догоняет. Эту фичу просили годами.
Сейчас она уже официально поддержана (championed), а значит, очень вероятно, что она действительно доедет.
И когда доедет, ты будешь ее использовать.
Не потому что это обязательно. А потому что так просто лучше.
Лично мне идея нравится. А тебе как эта фича в C#?🚬
👉 @KodBlog
goto может появиться в C# 15И ты будешь им пользоваться. Звучит стремно, да?
Но тут другая история.
Официально продвигаемое предложение для C# 15 добавляет labeled
break и continue.Это решает проблему, на которую все натыкаются в вложенных циклах.
И обычно мы решаем ее криво:
- Используем
goto со странными метками где-то внизу цикла.- Заводим флаги, которые “протекают” состоянием и прячут намерение.
Оба варианта делают код хуже для чтения и поддержки.
А теперь представь так:
→ Ты задаешь имя циклу, из которого хочешь выйти.
→ Потом пишешь ровно то, что имеешь в виду.
“Выйти из внешнего цикла.”
“Продолжить внешний цикл.”
И да, в других языках это уже есть:
→ Java, Kotlin, Rust, Go, Swift.
C# наконец догоняет. Эту фичу просили годами.
Сейчас она уже официально поддержана (championed), а значит, очень вероятно, что она действительно доедет.
И когда доедет, ты будешь ее использовать.
Не потому что это обязательно. А потому что так просто лучше.
Лично мне идея нравится. А тебе как эта фича в C#?
Please open Telegram to view this post
VIEW IN TELEGRAM
👍37❤7👎6
C# Primary Constructor пример:
👉 @KodBlog
// ДО .NET 8 (традиционный подход с конструктором)
public class UserService
{
private readonly HospitalDBContext _dbContext;
private readonly ILogger<UserService> _logger;
private readonly IEmailService _emailService;
public UserService(
HospitalDBContext dbContext,
ILogger<UserService> logger,
IEmailService emailService)
{
_dbContext = dbContext;
_logger = logger;
_emailService = emailService;
}
// Методы бизнес-логики здесь...
}
// ПОСЛЕ .NET 8 (с использованием первичного конструктора)
public class UserService(
HospitalDBContext _dbContext,
ILogger<UserService> _logger,
IEmailService _emailService)
{
// Методы бизнес-логики здесь...
}
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13
CQS и CQRS часто путают.
CQS = Command Query Separation
Это про дизайн классов: метод либо меняет состояние , либо возвращает значение
CQRS = Command Query Responsibility Segregation
CQRS логически разделяет потоки чтения и потоки записи данных. Хотя это не взаимоисключающие вещи, CQRS можно воспринимать как более строгую версию CQS.
👉 @KodBlog
CQS = Command Query Separation
Это про дизайн классов: метод либо меняет состояние , либо возвращает значение
CQRS = Command Query Responsibility Segregation
CQRS логически разделяет потоки чтения и потоки записи данных. Хотя это не взаимоисключающие вещи, CQRS можно воспринимать как более строгую версию CQS.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Это довольно приятное улучшение в Visual Studio.
Строки, состоящие только из пробелов, а также строки, где только скобки или знаки пунктуации, можно отображать меньшим шрифтом. Это немного возвращает вертикальное пространство и заодно снижает визуальный шум.
Эту настройку можно найти здесь:
Options -> Text Editor -> Advanced -> Compress Blank Lines
👉 @KodBlog
Строки, состоящие только из пробелов, а также строки, где только скобки или знаки пунктуации, можно отображать меньшим шрифтом. Это немного возвращает вертикальное пространство и заодно снижает визуальный шум.
Эту настройку можно найти здесь:
Options -> Text Editor -> Advanced -> Compress Blank Lines
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15❤2🥴2🤔1
Только что словил неприятный нюанс в
На Windows по умолчанию используется
Итог: для директорий никогда не используйте *.*, если только вы явно не ищете папки, в имени которых есть ..
Раньше я всегда использовал *.*, что, вероятно, на самом деле никогда не было корректным вариантом, но это работало и возвращало все папки при MatchType.Win32.
👉 @KodBlog
GetDirectories: когда ты явно передаешь EnumerationOptions, режим по умолчанию становится Simple.На Windows по умолчанию используется
Win32, когда запускаешь без этого, из-за чего старый синтаксис *.* начинает ломатьсяИтог: для директорий никогда не используйте *.*, если только вы явно не ищете папки, в имени которых есть ..
Раньше я всегда использовал *.*, что, вероятно, на самом деле никогда не было корректным вариантом, но это работало и возвращало все папки при MatchType.Win32.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Blazor Minimum Project Templates v11.0.100-preview.1 получили поддержку таргета net11.0.
Если хочется стартовать с максимально чистого Blazor-шаблона, это как раз тот случай: без JS, без CSS-библиотек, с упором на чистый C#.
Можно ставить и пробовать уже сейчас для .NET 11 preview.
https://github.com/jsakamoto/BlazorMinimumTemplates
👉 @KodBlog
Если хочется стартовать с максимально чистого Blazor-шаблона, это как раз тот случай: без JS, без CSS-библиотек, с упором на чистый C#.
Можно ставить и пробовать уже сейчас для .NET 11 preview.
https://github.com/jsakamoto/BlazorMinimumTemplates
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤1
Чувак сделал намеренно уязвимое dotnet приложение 👀
Многие советы по безопасности в .NET остаются слишком абстрактными, пока ты не увидишь баг прямо в коде.
Поэтому этот проект, где всё намеренно сделано неправильно. Это намеренно уязвимое .NET-приложение, в котором собрано более 50 распространённых реальных ошибок, которые могут проскочить в обычный бизнес-код.
Ссылка - https://github.com/AlexGoOn/the-most-vulnerable-dotnet-app
Некоторые из включённых вещей:
👉 @KodBlog
Многие советы по безопасности в .NET остаются слишком абстрактными, пока ты не увидишь баг прямо в коде.
Поэтому этот проект, где всё намеренно сделано неправильно. Это намеренно уязвимое .NET-приложение, в котором собрано более 50 распространённых реальных ошибок, которые могут проскочить в обычный бизнес-код.
Ссылка - https://github.com/AlexGoOn/the-most-vulnerable-dotnet-app
Некоторые из включённых вещей:
Инъекционные атаки (SQL, command, template, LDAP, XML, logs)
Cross-Site Scripting (stored, reflected, в атрибутах, в SVG)
Небезопасная загрузка файлов (path traversal, Zip Slip, произвольная запись файлов)
Проблемы с криптографией (hashing, ECB, предсказуемый random)
Сериализация (XXE, XML bomb, binary, YAML)
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍3🤔1
8 лет опыта научили меня, что кидать исключения дорого.
Поэтому я начал делать так:
Раньше я бросал исключения, когда:
- пользователь не найден
- переданы невалидные параметры
- результат метода
И всю логику обработки я выносил на вызывающую сторону, которая теперь должна знать, какое именно исключение прилетело и как на него реагировать.
Но реальность такая: исключения отлично подходят для ошибок, с которыми ты не знаешь, что делать.
К счастью, большинство ошибок можно обработать, и вот как:
Паттерн Result.
Вместо того чтобы кидать исключения, методы возвращают объект
Ещё стоит подумать о своей кастомной
В своих проектах я люблю иметь две версии: не-дженерик (для
Я предпочитаю свою реализацию, но если тебе это не заходит, можно взять готовые библиотеки, например FluentResults.
👉 @KodBlog
Поэтому я начал делать так:
Раньше я бросал исключения, когда:
- пользователь не найден
- переданы невалидные параметры
- результат метода
nullИ всю логику обработки я выносил на вызывающую сторону, которая теперь должна знать, какое именно исключение прилетело и как на него реагировать.
Но реальность такая: исключения отлично подходят для ошибок, с которыми ты не знаешь, что делать.
К счастью, большинство ошибок можно обработать, и вот как:
Паттерн Result.
Вместо того чтобы кидать исключения, методы возвращают объект
Result, который явно показывает успех/провал и содержит либо успешное значение, либо информацию об ошибке.Ещё стоит подумать о своей кастомной
Error-модели, где ты будешь нормально, описательно расписывать все типы ошибок и использовать её внутри Result.В своих проектах я люблю иметь две версии: не-дженерик (для
void-методов) и дженерик (обёртка для конкретного результата). Так намерение кода читается сразу и без гаданий.Я предпочитаю свою реализацию, но если тебе это не заходит, можно взять готовые библиотеки, например FluentResults.
Please open Telegram to view this post
VIEW IN TELEGRAM
🥴12❤9👍7🤔3
Оператор LINQ FullJoin() появится в dotnet 11?
https://github.com/dotnet/runtime/issues/124787
👉 @KodBlog
https://github.com/dotnet/runtime/issues/124787
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Когда стоит использовать паттерн Outbox?
Паттерн Outbox хранит исходящие сообщения в таблице базы данных, а потом фоновый процесс публикует их в брокер сообщений.
Зачем вообще заморачиваться?
Потому что в распределённых системах всё ломается: падают downstream-сервисы, отваливается сеть и т.д.
Если публиковать сообщения прямо внутри обработки запроса, есть риск их потерять, когда что-то пойдёт не так.
Outbox опирается на атомарные транзакции БД:
✅ Сохранить состояние приложения
✅ Сохранить сообщение в Outbox (либо оба шага, либо ни один)
А дальше фоновый процесс уже безопасно доставляет сообщение.
Важно помнить: Outbox решает надёжность публикации.
А на стороне консюмера всё равно нужна идемпотентность, чтобы нормально переживать ретраи.
Хочешь глубже?
Полная статья тут: https://milanjovanovic.tech/blog/implementing-the-outbox-pattern
👉 @KodBlog
Паттерн Outbox хранит исходящие сообщения в таблице базы данных, а потом фоновый процесс публикует их в брокер сообщений.
Зачем вообще заморачиваться?
Потому что в распределённых системах всё ломается: падают downstream-сервисы, отваливается сеть и т.д.
Если публиковать сообщения прямо внутри обработки запроса, есть риск их потерять, когда что-то пойдёт не так.
Outbox опирается на атомарные транзакции БД:
А дальше фоновый процесс уже безопасно доставляет сообщение.
Важно помнить: Outbox решает надёжность публикации.
А на стороне консюмера всё равно нужна идемпотентность, чтобы нормально переживать ретраи.
Хочешь глубже?
Полная статья тут: https://milanjovanovic.tech/blog/implementing-the-outbox-pattern
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4❤3
C# records как value objects?
Records по задумке иммутабельные, и у них структурное сравнение (равенство по значениям).
А именно это обычно и нужно от value object.
Плюс сверху получаем pattern matching, короткий синтаксис и deconstruction.
👉 @KodBlog
Records по задумке иммутабельные, и у них структурное сравнение (равенство по значениям).
А именно это обычно и нужно от value object.
Плюс сверху получаем pattern matching, короткий синтаксис и deconstruction.
public class Booking
{
public Address Address { get; init; }
public DateRange Period { get; init; }
}
public record Address(
string Street,
string City,
string State,
string Country,
string ZipCode);
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9😁1
Каждый раз, когда ты пишешь очередной новенький
ты на самом деле принимаешь решение по производительности.
Большинство разработчиков воспринимают структуры данных как контейнеры. А это не так. Это контракты по перформансу.
Вот как полезно думать о самых популярных структурах в .NET, по-практически:
Array
Бери, когда размер фиксирован и нужен честный O(1) доступ по индексу.
Самый быстрый вариант. Нет ресайза. Нет сюрпризов.
List<T>
Отличный дефолтный выбор, пока не упираешься в ресайз.
Под капотом при росте capacity копируется весь массив.
Dictionary<TKey, TValue>
В среднем O(1) на поиск.
Но плохое распределение хеша -> коллизии -> деградация скорости.
Stack<T>
Идеален для рекурсии, парсинга, undo/redo.
Но глубокая рекурсия? Привет, StackOverflow (сайт) или stack overflow (ошибка).
Queue<T>
FIFO. Отлично для фоновой обработки и пайплайнов.
Типа планирования задач, обработки сообщений.
Tree / Graph
Используются чаще, чем кажется:
роутинг, индексация, разрешение зависимостей, поиск.
Смысл не в том, чтобы заучивать Big-O.
Смысл понимать:
- как выделяется память
- как работает ресайз
- что происходит под нагрузкой
- на какой компромисс ты соглашаешься
Хорошие инженеры пишут код, который работает.
Классные инженеры знают, почему он работает и в какой момент перестанет.
👉 @KodBlog
List<>,ты на самом деле принимаешь решение по производительности.
Большинство разработчиков воспринимают структуры данных как контейнеры. А это не так. Это контракты по перформансу.
Вот как полезно думать о самых популярных структурах в .NET, по-практически:
Array
Бери, когда размер фиксирован и нужен честный O(1) доступ по индексу.
Самый быстрый вариант. Нет ресайза. Нет сюрпризов.
List<T>
Отличный дефолтный выбор, пока не упираешься в ресайз.
Под капотом при росте capacity копируется весь массив.
Dictionary<TKey, TValue>
В среднем O(1) на поиск.
Но плохое распределение хеша -> коллизии -> деградация скорости.
Stack<T>
Идеален для рекурсии, парсинга, undo/redo.
Но глубокая рекурсия? Привет, StackOverflow (сайт) или stack overflow (ошибка).
Queue<T>
FIFO. Отлично для фоновой обработки и пайплайнов.
Типа планирования задач, обработки сообщений.
Tree / Graph
Используются чаще, чем кажется:
роутинг, индексация, разрешение зависимостей, поиск.
Смысл не в том, чтобы заучивать Big-O.
Смысл понимать:
- как выделяется память
- как работает ресайз
- что происходит под нагрузкой
- на какой компромисс ты соглашаешься
Хорошие инженеры пишут код, который работает.
Классные инженеры знают, почему он работает и в какой момент перестанет.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤6
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🤯7🥴4❤3🔥1
Паттерн Builder в реальном мире на C#: полная реализация
Посмотрите, как паттерн Builder работает на практике, на полноценном реальном примере на C#. Пошаговая реализация конфигурационной системы, которая показывает поэтапную сборку объекта.
Статья здесь
👉 @KodBlog
Посмотрите, как паттерн Builder работает на практике, на полноценном реальном примере на C#. Пошаговая реализация конфигурационной системы, которая показывает поэтапную сборку объекта.
Статья здесь
Please open Telegram to view this post
VIEW IN TELEGRAM
Dev Leader
Builder Pattern Real-World Example in C#: Complete Implementation
See Builder pattern in action with a complete real-world C# example. Step-by-step implementation of a configuration system demonstrating step-by-step object con
❤5