C# Portal | Программирование
13.9K subscribers
1.15K photos
126 videos
29 files
928 links
Присоединяйтесь к нашему каналу и погрузитесь в мир для C#-разработчика

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

Менеджер: @Spiral_Yuri

РКН: https://clck.ru/3FocB6
Download Telegram
C# Primary Constructor пример:

// ДО .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)
{
// Методы бизнес-логики здесь...
}


👉 @KodBlog
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
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Это довольно приятное улучшение в Visual Studio.

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

Эту настройку можно найти здесь:

Options -> Text Editor -> Advanced -> Compress Blank Lines

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍152🥴2🤔1
Только что словил неприятный нюанс в GetDirectories: когда ты явно передаешь EnumerationOptions, режим по умолчанию становится Simple.

На Windows по умолчанию используется Win32, когда запускаешь без этого, из-за чего старый синтаксис *.* начинает ломаться

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

Раньше я всегда использовал *.*, что, вероятно, на самом деле никогда не было корректным вариантом, но это работало и возвращало все папки при MatchType.Win32.

👉 @KodBlog
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
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍71
Чувак сделал намеренно уязвимое dotnet приложение 👀

Многие советы по безопасности в .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)


👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍3🤔1
8 лет опыта научили меня, что кидать исключения дорого.

Поэтому я начал делать так:

Раньше я бросал исключения, когда:

- пользователь не найден
- переданы невалидные параметры
- результат метода null

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

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

К счастью, большинство ошибок можно обработать, и вот как:

Паттерн Result.

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

Ещё стоит подумать о своей кастомной Error-модели, где ты будешь нормально, описательно расписывать все типы ошибок и использовать её внутри Result.

В своих проектах я люблю иметь две версии: не-дженерик (для void-методов) и дженерик (обёртка для конкретного результата). Так намерение кода читается сразу и без гаданий.

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

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🥴129👍7🤔3
Оператор LINQ FullJoin() появится в dotnet 11?

https://github.com/dotnet/runtime/issues/124787

👉 @KodBlog
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
Please open Telegram to view this post
VIEW IN TELEGRAM
👍43
C# records как value objects?

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);


👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9😁1
Каждый раз, когда ты пишешь очередной новенький 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.

Смысл понимать:

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

Хорошие инженеры пишут код, который работает.

Классные инженеры знают, почему он работает и в какой момент перестанет.

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
👍76
GitHub Copilot SDK для .NET: полное руководство разработчика

Разберись с GitHub Copilot SDK для .NET в этом полном гайде для разработчиков. Собирай кастомных AI-агентов на базе CopilotClient и CopilotSession, со стримингом, tools и поддержкой нескольких моделей в C#.

Статья здесь

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
5
Пример Vertical Slice Architecture в ASP.NET

Я один такой, кто складывает вообще всё в один файл?

С этим работать просто мечта 😍

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8🤯7🥴43🔥1
Паттерн Builder в реальном мире на C#: полная реализация

Посмотрите, как паттерн Builder работает на практике, на полноценном реальном примере на C#. Пошаговая реализация конфигурационной системы, которая показывает поэтапную сборку объекта.

Статья здесь

👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
5
Как применять EF-миграции в продакшене?

Самый распространенный подход: накатывать их через CLI командой Update-Database.

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

Еще лучше, если у вас есть DBA.

CREATE TABLE IF NOT EXISTS "__EFMigrationsHistory" (
"MigrationId" character varying(150) NOT NULL,
"ProductVersion" character varying(32) NOT NULL,
CONSTRAINT "PK___EFMigrationsHistory" PRIMARY KEY ("MigrationId")
);

START TRANSACTION;

CREATE TABLE "Products" (
"Id" integer GENERATED BY DEFAULT AS IDENTITY,
"Name" character varying(100) NOT NULL,
"Description" character varying(1000),
"Price" numeric(18,2) NOT NULL,
CONSTRAINT "PK_Products" PRIMARY KEY ("Id"),
CONSTRAINT "CK_Price_NotNegative" CHECK (Price > 0)
);

CREATE UNIQUE INDEX "IX_Products_Name" ON "Products" ("Name");

INSERT INTO "__EFMigrationsHistory" ("MigrationId", "ProductVersion")
VALUES ('20240516095344_Create_Database', '8.0.5');

COMMIT;


👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🥴9🤔1
Отсутствие нейминг-конвенций в коде меня дико бесит.

Можешь с этим что-нибудь сделать?

Только без истерик в PR (так не надо).

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

Вот пример для именования command handler-ов.

[Fact]
public void CommandHandler_ShouldHave_NameEndingWith_CommandHandler()
{
Types.InAssembly(ApplicationAssembly)
.That()
.ImplementInterface(typeof(ICommandHandler<>))
.Or()
.ImplementInterface(typeof(ICommandHandler<,>))
.Should()
.HaveNameEndingWith("CommandHandler")
.GetResult()
.ShouldBeSuccessful();
}


👉 @KodBlog
Please open Telegram to view this post
VIEW IN TELEGRAM
🥴76👍4🤔1