C# 1001 notes
الذهاب إلى القناة على Telegram
Регулярные короткие заметки по C# и .NET. Просто о сложном для каждого. admin - @haarrp
إظهار المزيد6 617
المشتركون
+124 ساعات
+537 أيام
+4730 أيام
أرشيف المشاركات
6 618
👩💻 🎯 Открытый урок «Асинхронность в C#: за гранью await. Паттерны, ошибки и оптимизация для профессионалов».
🗓 17 июля в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «C# Developer. Professional».
Что будет на вебинаре:
✔️ Разбор сложных сценариев: цепочки задач, параллельный async, комбинирование с параллелизмом (Task, Parallel, async).
✔️ Распространенные ошибки (deadlocks, async void, контексты синхронизации) и как их точно избегать.
✔️ Паттерны: CancellationTokens, ValueTask, IAsyncDisposable, кастомные awaiterы (обзорно).
✔️ Когда и как измерять производительность async кода, что может стать узким местом.
✔️ Best practices для реальных высоконагруженных сценариев.
Кому будет полезно:
- Разработчикам C# с опытом (Mid+/Senior), которые активно используют async/await.
- Тем, кто сталкивался с непонятными блокировками или проблемами производительности в асинхронном коде.
- Тем, кто хочет писать более надежный и эффективный асинхронный код.
🔗 Ссылка на регистрацию: https://otus.pw/SIHc/
6 618
Устали править копипастные участки кода и бороться с хаосом в проекте?
⏺️ Приглашаем на открытый урок «Переиспользуемый код на C#: архитектурный подход» 15 июля в 20:00 МСК. Разберём, как строить приложение по принципам SOLID, DRY, KISS и YAGNI и избавляться от дублирования на уровне архитектуры. Вы увидите, как декомпозировать систему на слои, внедрять зависимости через абстракции и собирать «Lego-приложение» для разных интерфейсов.
🔴 Встречаемся 15 июля в 20:00 МСК.
➡️ Успейте зарегистрироваться на урок количество участников ограничено: https://otus.pw/QsiE/?erid=2W5zFJGhdct
Реклама. ООО "ОТУС ОНЛАЙН-ОБРАЗОВАНИЕ". ИНН 9705100963.
6 618
🎯 Using .NET Aspire With the Docker Publisher — практическое руководство от Milan Jovanović
.NET Aspire — это современный фреймворк от Microsoft для создания облачных микросервисов. В статье показано, как автоматически интегрировать Docker Compose в .NET‑приложение с помощью нового инструмента — Aspire Docker Publisher.
✅ Что вы узнаете:
1. Как описать окружение прямо в C#:
builder.AddDockerComposeEnvironment("aspire-docker-demo");
var postgres = builder.AddPostgres("database").WithDataVolume();
var redis = builder.AddRedis("cache");
var webApi = builder.AddProject<Projects.Web_Api>("web-api")
.WithReference(postgres).WaitFor(postgres)
.WithReference(redis).WaitFor(redis);
builder.Build().Run();
2. Как опубликовать проект:
dotnet tool install --global aspire.cli --prerelease
aspire publish -o docker-compose-artifacts
После чего автоматически создаётся docker-compose.yml и .env.
3. Что входит в результат:
- Готовый docker-compose.yml со всеми зависимостями
- Поддержка портов, переменных среды, volume и сетей
- Полная инфраструктура, которую можно деплоить хоть на VPS
4. Как это работает на проде:
- Всё, что нужно: скопировать артефакты → docker compose up -d
- Можно легко обернуть через Nginx или Traefik, подключить SSL
🧠 Почему это удобно:
- Не нужно вручную писать YAML — всё в коде
- Повышается воспроизводимость и читаемость инфраструктуры
- Упрощает переход от локальной разработки к боевому деплою
🔗 Статья: www.milanjovanovic.tech/blog/using-dotnet-aspire-with-the-docker-publisher6 618
Трюк: добавление элементов в словарь со списками через `??=`
var dict = new Dictionary<string, List<int>>();
string key = "numbers";
int item = 42;
// Обычный способ:
if (!dict.TryGetValue(key, out var list))
{
list = new List<int>();
dict[key] = list;
}
list.Add(item);
// Короткий трюк:
(dict[key] ??= new List<int>()).Add(item);
Разбор:
- При обращении к dict[key] отсутствующий ключ вернёт default(List<int>), то есть null.
- Оператор ??= проверяет левую часть на null и, если она null, присваивает справа новое значение.
- В нашем случае, если dict[key] был null, создаётся новый List<int> и сразу сохраняется в словаре.
- После этого метод .Add(item) вызывается уже на существующем списке.
- В результате за одну строчку мы и проверили наличие, и создали новый список при необходимости, и добавили элемент.6 618
⁉️ Тормозит карьерный рост? Упираетесь в потолок с текущими навыками на C#? Новые проекты ускользают, а вы застряли на уровне Middle?
🔥 Пройдите тест! 💻 Ответьте на 32 вопроса и узнайте, достаточно ли у вас знаний, для обучения на онлайн-курсе «C# Developer. Professional» от OTUS.
Вас ждут реальные проекты в Scrum-командах, продвинутый уровень работы с C#, освоение SQL и NoSQL, кэширование, Unit-тесты и CI/CD.
🦾 Пора стать тем самым разработчиком, которого компании хантят друг у друга. Нужно только перейти на принципиально новый уровень.
👉 Пройдите тест и присоединяйтесь к группе: https://otus.pw/WEvA/
#реклама
О рекламодателе
6 618
🖥Быстрая сортировка (QuickSort) с использованием рекурсии
Проблема: cортировка больших массивов может быть неэффективной при использовании простых алгоритмов, таких как сортировка пузырьком или вставками.
Решение: Автор в книге Algorithms and Data Structures for OOP With C# демонстрирует реализацию QuickSort — одного из самых эффективных алгоритмов сортировки на практике, с рекурсивным разбиением массива.
Пример кода:
public class QuickSortExample
{
public void QuickSort(int[] arr, int low, int high)
{
if (low < high)
{
int pi = Partition(arr, low, high);
QuickSort(arr, low, pi - 1);
QuickSort(arr, pi + 1, high);
}
}
private int Partition(int[] arr, int low, int high)
{
int pivot = arr[high];
int i = (low - 1);
for (int j = low; j < high; j++)
{
if (arr[j] < pivot)
{
i++;
(arr[i], arr[j]) = (arr[j], arr[i]);
}
}
(arr[i + 1], arr[high]) = (arr[high], arr[i + 1]);
return i + 1;
}
}
Преимущества:
— Быстрая сортировка даже больших наборов данных
— Средняя сложность O(n log n)
— Эффективное использование памяти за счет рекурсии6 618
🐢 Столкнулись с «тормозным» C#-кодом? Медленные алгоритмы могут растянуть выполнение задачи на минуты вместо миллисекунд.
📅 Приглашаем на открытый урок «Анализ сложности алгоритмов и сортировка на C#» 3 июля в 20:00 МСК.
Разберём, что такое Big O, какие факторы влияют на скорость, и на практике напишем пузырьковую, вставками и другие сортировки.
Вы увидите, как измерять время выполнения, сравнивать производительность и выбирать самый эффективный алгоритм. После занятия ваш код станет быстрее, а техническое интервью — проще.
Регистрируйтесь сейчас — урок проходит перед стартом курса «C# Developer»: https://otus.pw/yQzK/?erid=2W5zFJSuoQ4
Реклама. ООО "ОТУС ОНЛАЙН-ОБРАЗОВАНИЕ". ИНН 9705100963.
6 618
🖥 Задача «Перехват исключений и потеря контекста» (C# 12)
Дан код:
using System;
using System.Runtime.ExceptionServices;
class Program
{
static void Main()
{
try
{
Console.WriteLine(Foo());
}
catch (Exception ex)
{
Console.WriteLine($"Catch: {ex.Message}");
}
}
static int Foo()
{
try
{
return Bar();
}
finally
{
throw new Exception("finally in Foo");
}
}
static int Bar()
{
try
{
throw new Exception("error in Bar");
}
finally
{
Console.WriteLine("Bar finally executed");
}
}
}
Вопросы:
• Что напечатает программа и почему?
• В каком порядке выполняются блоки try / finally?
• Какая из двух ошибок дойдёт до catch, а какая потеряется?
• Как изменить код, чтобы не терять информацию о первой ошибке?
Разбор:
• Bar бросает Exception("error in Bar"). Прежде чем исключение покинет метод, выполняется его finally, выводя Bar finally executed.
• Управление переходит в Foo. Там срабатывает finally, который бросает новое исключение ("finally in Foo").
• По правилам CLR новое исключение из finally заменяет текущее. Первая ошибка пропадает.
• В Main перехватывается только «finally in Foo».
Консольный вывод:
Bar finally executed
Catch: finally in Foo
Как сохранить обе ошибки
Обернуть второе исключение так, чтобы первая причина не потерялась, например:
finally
{
var pending = new Exception("finally in Foo");
throw new AggregateException("Foo failed", pending);
}
или переслать исходное исключение через ExceptionDispatchInfo:
Exception pending = null;
static int Foo()
{
try
{
return Bar();
}
catch (Exception ex)
{
pending = ex; // сохраняем первую причину
throw;
}
finally
{
if (pending != null)
ExceptionDispatchInfo.Capture(pending).Throw();
}
}```
Так ни одна ошибка не будет потеряна, а отладка станет нагляднее.6 618
Реферальная программа для тех, кто не работает в Ozon:
порекомендуйте C#-разработчика уровня senior и заработайте 150 000 ₽.
Посмотреть вакансии, которые включает программа: https://s.ozon.ru/rja14Mz
6 618
In-memory кэш в .NET: плюсы и минусы
✅ Плюсы:
• Очень быстрый
• Легко реализуется
• Не требует внешних зависимостей
⚠️ Минусы:
• Данные теряются при перезапуске
• Работает только в пределах одного инстанса
• Нет шаринга между приложениями
📌 Нужно больше — переходите на распределённый кэш.
Redis — топовый выбор, и в .NET есть два стабильных клиента:
•
StackExchange.Redis
• Microsoft.Extensions.Caching.StackExchangeRedis
📘 Хотите понять, когда и как использовать оба подхода?
Вот полный гайд:
https://milanjovanovic.tech/blog/caching-in-aspnetcore-improving-application-performance6 618
💣 Как настроить отказоустойчивое хранилище данных? Дарим гайд за прохождение теста по HighLoad!
🏆 Пройди тест из 29 вопросов, проверь свой уровень знаний и получи файл “Как настроить отказоустойчивое хранилище данных“!
Тест проводится в рамках курса Highload Architect
👉 Пройти тест и забрать файл: https://otus.pw/348d/?erid=2W5zFJdK4JC
Если успешно пройдешь тест, то так же сможешь забронировать место в группе по выгодной цене!
🎫 Курс можно приобрести в рассрочку
Реклама. ООО "ОТУС ОНЛАЙН-ОБРАЗОВАНИЕ". ИНН 9705100963.
6 618
[Best Practice] Явная конфигурация приложений ASP.NET Core
В большинстве существующих .NET-проектов конфигурация оказывается неочевидной, хотя в экосистеме .NET уже есть всё необходимое для ясной и понятной настройки ASP.NET Core веб-приложений с DI.
Как устроена конфигурация ASP.NET Core
- Источники (в порядке приоритета):
1. Host configuration
2.
appsettings.json
3. appsettings.{Environment}.json
4. User secrets (в среде Development)
5. переменные окружения
6. аргументы командной строки
При дублировании ключей побеждает источник, указанный позже :contentReference[oaicite:0]{index=0}.
Выбор способа доступа к настройкам
- Через IConfiguration
- Через IOptions<T> / IOptionsMonitor<T>
Предпочтение паттерну Options даёт типобезопасный доступ к группам настроек и делает их использование очевидным :contentReference[oaicite:1]{index=1}.
Где хранить разные параметры
- `appsettings.json` — общие настройки (без секретов).
- `appsettings.{Environment}.json` — переопределения для конкретного окружения.
- User Secrets (`secrets.json`) — локальные секреты (пароли, ключи API); не используйте appsettings.json или appsettings.Development.json для них :contentReference[oaicite:2]{index=2}.
- Azure Key Vault — производственные секреты через builder.Configuration.AddAzureKeyVault(...) :contentReference[oaicite:3]{index=3}.
- Переменные окружения и CLI — для срочных или разовых переопределений.
Рекомендации по внедрению
- Избегайте дублирования ключей — задавайте значение только там, где оно действительно меняется.
- В README укажите, что разработчикам нужно получить secrets.json из менеджера паролей и настроить User Secrets.
- В IaC-скриптах чётко обозначьте необходимые секреты и параметры для каждого окружения.
Преимущества подхода
- Новым участникам проекта легко разобраться в конфигурации — каждый ключ встречается в одном месте.
- Возрастает поддерживаемость и прозрачность настроек.
- Упрощается автоматизация развёртывания (IaC): сразу видно, какие секреты и параметры требуются.
Читать6 618
👶 Junior developer пишет:
notInactive, tempBool
🧑 Middle developer пишет: hadSubscriptionOnceUponATime
🧓 Senior developer пишет: hasSubscription, isActive
🤔 Почему так происходит?
👉 Потому что булевы переменные — просты по сути, но часто используются неинтуитивно, что делает код запутанным и плохо поддерживаемым.
Вот 7 простых правил, как работать с булевыми значениями в C# и резко улучшить читаемость вашего кода:
1. 🚫 Избегайте двойных отрицаний
❌ user.IsNotActive
✅ user.IsActive
❌ user.HasNoDept
✅ user.HasDept
❌ creditCard.IsNotExpired
✅ creditCard.IsExpired
Двойные отрицания сбивают с толку и делают логику трудной для чтения.
2. ✅ Используйте понятные префиксы
✅ Is: user.IsActive
✅ Has: user.HasDept
✅ Should: order.ShouldBeCanceled
Префиксы мгновенно раскрывают назначение переменной.
3. 🔤 Предпочитайте единственное число
❌ areUsers
✅ hasUsers
Единственное число делает значение ясным и конкретным.
4. 🎯 Используйте прилагательные для описания состояния
❌ CancelOrder
✅ IsOrderCanceled
Булевы переменные должны описывать состояние, а не действие.
5. ⏱ Используйте настоящее время
❌ card.WasExpired
✅ card.IsExpired
Текущие состояния — проще и универсальнее в коде.
6. 🔁 Принцип раннего возврата (Return Early)
Пишите условия и булевы проверки так, чтобы код читался сверху вниз, как история — коротко, логично, понятно.
7. ⚠️ Не передавайте булевы параметры
❌ SendEmail(true)
✅ SendEmail(SendMode.Immediate)
Используйте перечисления или именованные константы — они понятны без документации.
📌 Вывод:
Хорошие имена булевых переменных — это не косметика, а основа читаемости и архитектурной чистоты.
Хорошо названный isActive понятнее, чем любые комментарии и тесты.
💬 А ты какие правила используешь для наименования булевых переменных? Делись в комментариях 👇6 618
Repost from C++ Academy
🚀 Разработчик показал движок на C, который работает в 14 раз быстрее Unity в браузере — и теперь доступна онлайн-демо.
Многие не поверили в заявленную разницу в производительности, поэтому он выложил демо в открытый доступ. Сравнение проводится с реальным Unity-проектом, выложенным на GitHub.
🛠️ C-движок демонстрирует:
• Существенно более высокую FPS в браузере
• Минимальную просадку при рендеринге
• Низкий overhead по сравнению с WebAssembly-сборкой Unity
💬 Автор пока не решил, выкладывать ли исходники C-версии — рассматривает вариант лицензии CC (non-commercial).
🔗 Демо: https://cgamedev.com/
🔗 Код: https://github.com/gabrieldechichi/unity_webglperftest
@cpluspluc
6 618
💣 Большая сила - большая ответственность.
А ты справишься с тестом по HighLoad?
🏆 Пройди тест из 29 вопросов, проверь свой уровень знаний и получи скидку на онлайн-курс «Highload Architect» от OTUS!
Если успешно пройдешь тест, сможешь забронировать место в группе по выгодной цене!
🎫 Курс можно приобрести в рассрочку
👉 Пройти тест и забрать скидку: https://otus.pw/pdy8/?erid=2W5zFGJXEcY
Реклама. ООО "ОТУС ОНЛАЙН-ОБРАЗОВАНИЕ". ИНН 9705100963.
6 618
🗂️ Entity Framework Core — ORM нового поколения для работы с БД. Этот инструмент от Microsoft кардинально меняет подход к взаимодействию с реляционными и NoSQL базами данных.
Для работы инструмент предоставляет мощный слой абстракции, позволяя работать с данными как с объектами, автоматизируя CRUD-операции и миграции схемы. EF Core поддерживает широкий пласт СУБД: от классических SQL Server и PostgreSQL до документоориентированной Cosmos DB. Для SQLite-разработчиков есть отдельный оптимизированный провайдер Microsoft.Data.Sqlite.
🤖 GitHub
6 618
🤖 Два подхода DDD: Rich Model vs Anemic Model
Приглашаем на открытый урок.
🗓 24 июня в 20:00 МСК
🆓 Бесплатно. Урок в рамках старта курса «C# Developer Professional».
На вебинаре:
✔️ Разбор концепций: чем анемичная модель (Anemic Model) отличается от богатой (Rich Model)
✔️ Рассмотрим, когда что выбрать
✔️ Оценим преимущества и недостатки каждой из моделей
Кому будет полезно:
- Всем, кто стремится глубже понять DDD
- .NET-разработчикам, проектирующим сложные системы с долгосрочной поддержкой
- Студентам, изучающим паттерны проектирования и чистую архитектуру
Чему научатся участники по итогам вебинара:
- Понимать, когда код попадает в антипаттерн Anemic Model
- Проектировать сущности с бизнес-логикой внутри
- Выбирать компромиссы: скорость разработки (Anemic) vs гибкость/безопасность (Rich).
🔗 Ссылка на регистрацию: https://otus.pw/lgGf/
#реклама
О рекламодателе
6 618
+1
⚡️ Если ты запускаешь десяток терминалов для старта приложения
С .NET Aspire можно запускать backend, frontend и все зависимости одновременно — быстро и удобно!
Смотри, как это сделать: justkeepcoding.tech/blog/integrating-angular-into-dotnet-aspire
6 618
Балансировка и геораспределение: как создать быстрое и надёжное приложение для всего мира
На вебинаре разберём, как крупные компании — такие как Netflix, Amazon и другие — делают свои сервисы доступными для пользователей по всему миру без задержек и сбоев.
На вебинаре вы:
— Как работают балансировщики и «умные» прокси.
— Что такое геораспределение и зачем оно критично для масштабируемых сервисов.
— Как грамотно распределять трафик между дата-центрами.
— Частые ошибки при проектировании глобальных систем — и как их избежать.
👉 Регистрация и подробности о курсе Highload Architect: https://tglink.io/e860f3379195?erid=2W5zFGLzfAg
Бесплатное занятие приурочено к старту курса Highload Architect, обучение на котором позволит освоить решения, которые выдерживают большое количество запросов в секунду и правильно оптимизировать работоспособность серверов.
Реклама. ООО "ОТУС ОНЛАЙН-ОБРАЗОВАНИЕ". ИНН 9705100963.
6 618
🌺 Radzen Blazor Components — 90+ UI-компонентов для Blazor. Этот набор открытых компонентов позволяет быстро собирать интерфейсы на Blazor без зависимостей от JavaScript-фреймворков. Все элементы нативные для Blazor, написанные на C#, что обеспечивает полную интеграцию с экосистемой .NET.
Проект активно развивается: новые компоненты появляются регулярно, а не ждут квартальных релизов. Для коммерческой разработки доступна платная подписка с расширенной поддержкой, но базовая функциональность остаётся бесплатной под лицензией MIT.
🤖 GitHub
@csharp_ci
