C# (C Sharp) programming
18.1K subscribers
991 photos
52 videos
8 files
793 links
По всем вопросам- @notxxx1

Реестр РКН: https://clck.ru/3Fk3kb

#VRHSZ
Download Telegram
Задачка по C# 14: обновили проект на .NET 10, и код молча начал работать иначе

Что выведет этот код?


var c = new Counter();
c.Value = 5;

Console.WriteLine($"{c.Value} {c.Raw} {c.GetRaw()}");

class Counter
{
private int field = 100;

public int Value
{
get => field;
set => field = value;
}

public int Raw => field;

public int GetRaw() => field;
}


Варианты:


A) 5 5 5
😎 5 100 100
C) 5 0 100
D) Код не скомпилируется


Ответ: **C) 5 0 100**

В C# 14 слово `field` внутри аксессоров свойства стало ключевым. Теперь оно означает **скрытое поле, которое компилятор создаёт для этого свойства**, даже если в классе уже есть член с таким именем.

Поэтому в этом коде три разных `field`:

```
Value → своё скрытое поле: записали 5, прочитали 5
Raw → тоже аксессор, но со своим скрытым полем: в него никто не писал, значит 0
GetRaw() → обычный метод, ключевое слово тут не действует, это поле класса: 100
```

Главная ловушка в строке `public int Raw => field;`. Выглядит как обычный метод-однострочник, но это свойство, а значит get-аксессор. Поле класса со значением 100 здесь вообще не видно.

До C# 14 этот же код выводил `5 5 5`: все три обращения шли к одному полю класса. После обновления он компилируется и тихо меняет поведение. Чтобы обратиться к старому полю, внутри аксессоров нужно писать `this.field` или `
@field`.
🧱 Модульный монолит легко потерять одним удобным JOIN.

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

Границы стоит закреплять и в базе:

• Отдельная схема и роль PostgreSQL для каждого модуля.
• Роль получает права только на свои данные.
• В EF Core каждому модулю выделяется собственный DbContext и подключение с его учётными данными.
• Чужие данные доступны через API, события или специально опубликованные представления с правами только на чтение.

Так случайный запрос к чужой таблице остановит сама база. А выделять модуль в отдельный сервис впоследствии будет проще.

Нюанс: отдельная схема и search_path сами по себе доступа не ограничивают. Границу обеспечивают права ролей на схемы и объекты.

https://milanjovanovic.tech/blog/how-to-keep-your-data-boundaries-intact-in-a-modular-monolith
Альфа-Банк ищет скиллового коллегу QA Fullstack на C#

Предлагаем полную удалёнку или гибридный график – у нас классные ИТ-офисы в Москве, Питере и Екатеринбурге.

Что нужно делать

– Разрабатывать автотесты на C#.
– Запускать функциональные, регрессионные и интеграционные тесты, включая API.
– Снижать количество дефектов в диалоге с разработкой и бизнесом.

Какие навыки важны

– Опыт автоматизации на C# и ручного тестирования от года.
– Знание API (SOAP, REST), SQL, основ клиент-серверной архитектуры и тест-дизайна.

Условия и развитие

– Сильное сообщество QA и C#-разработчиков: можно получить совет и поделиться опытом на митапе и в блоге на Хабре.
– Реальная перспектива роста: технический трек развития, в том числе до C#-лида

Оставляйте отклик по ссылке.
Helm-чарты прямо из C#, без запуска `helm` 🛠

HelmSharp позволяет рендерить шаблоны и управлять релизами Kubernetes внутри .NET-приложения.

Что умеет:

• Загружать чарты из папки и .tgz.
• Объединять values.yaml с пользовательскими параметрами.
• Упаковывать чарты и работать с HTTP-репозиториями.
• Устанавливать, обновлять, откатывать и удалять релизы.
• Хранить историю релизов в Kubernetes Secrets, совместимых с Helm v3.

Для начала:


dotnet add package HelmSharp.Action


Поддерживает .NET 8, 9 и 10, лицензия MIT.

Пригодится для собственных панелей управления и сервисов деплоя на C#. Совместимость с Helm пока частичная: свои чарты стоит проверить, особенно если они используют сложные шаблонные функции или расширения.

https://github.com/GaTTGeng/HelmSharp
Что на самом деле происходит с вашим async-методом: компилятор C# переписывает его в конечный автомат

Meziantou разобрал, во что превращается async-метод после компиляции. Сам метод становится заглушкой: она создаёт структуру-автомат, заводит билдер вроде AsyncTaskMethodBuilder, копирует параметры в поля, ставит состояние -1, вызывает Start и возвращает Task. Вся логика переезжает в MoveNext.

В Release автомат это struct, в Debug это class. Пока метод не засыпает, автомат живёт на стеке. Как только он приостанавливается, билдер упаковывает его в кучу. Поле state хранит точку возобновления: -1 значит выполняется, -2 завершён, 0 и выше номер await. В поля уходят только параметры и локальные переменные, которые нужны после await, остальные остаются локальными. Слоты под awaiter выделяются на тип, а не на каждый await, поэтому несколько await на одном типе делят одно поле.

Сам await превращается в switch по полю плюс регистрацию продолжения. Если awaiter уже завершён, код идёт дальше без остановки. Если нет, сохраняется состояние и awaiter, вызывается AwaitUnsafeOnCompleted, и MoveNext возвращается. Исключения ловятся сгенерированным try/catch и уходят в SetException, поэтому всплывают на await, а не в месте вызова. До первого незавершённого await метод выполняется синхронно.

Бенчмарки автора показывают цену этого механизма: синхронный цикл 2,7 нс, async без реального ожидания 47,9 нс, async с приостановкой на каждой итерации 8820 нс. Разница в сотни раз в горячих циклах заметна, так что await на каждом элементе лучше пересобирать. Мерить стоит только в Release, иначе картина искажается.

Источник: https://www.meziantou.net/how-the-csharp-compiler-rewrites-an-async-method.htm
Please open Telegram to view this post
VIEW IN TELEGRAM
Запрос проходит через несколько сервисов, обращается к базе данных и внешним API. Пользователь видит задержку или ошибку, а по отдельным записям в журналах трудно понять, на каком участке возникла проблема.

20 октября в 20:00 на открытом уроке курса «C# разработчик. Экспертный уровень» разберёте, как OpenTelemetry помогает превратить .NET-приложение из чёрного ящика в наблюдаемую систему.

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

На практике добавите средства сбора телеметрии в ASP.NET Core-приложение. Создадите собственные трассировки через ActivitySource и метрики через Meter, подключите автоматический сбор телеметрии для ASP.NET Core и HttpClient.

Урок проведёт Михаил Дмитриев.

Зарегистрироваться: https://otus.pw/f8Z4/?erid=2W5zFHPwe5P

Реклама. ООО "ОТУС ОНЛАЙН-ОБРАЗОВАНИЕ". ИНН 9705100963.
🛠 У .NET появился свой аналог rustup и nvm

Microsoft представила dotnetup: менеджер для установки и обновления .NET SDK и рантаймов. Пока в публичном превью.

Всё устанавливается в папку пользователя, без sudo и прав администратора. Можно держать стабильные версии, превью и ежедневные сборки рядом, а закрепление SDK через global.json сохраняется.

Несколько полезных команд:


dotnetup init # Настроить окружение
dotnetup list # Показать установленные версии
dotnetup update # Обновить отслеживаемые версии
dotnetup sdk install preview # Установить превью SDK


Можно отслеживать обновления внутри конкретной ветки или закрепить точную версию. При обновлении ненужные компоненты очищаются автоматически.

https://devblogs.microsoft.com/dotnet/introducing-dotnetup/
🌐 Новый `HttpClient` на каждый запрос? Под нагрузкой это может закончиться исчерпанием портов.

IHttpClientFactory создаёт новые экземпляры клиента, но переиспользует обработчики `HttpMessageHandler` и их пулы соединений. Поэтому освобождение клиента, полученного от фабрики, не уничтожает пул после каждого запроса.

Три способа использования:

• Обычный клиент: CreateClient() для простых сценариев. Общие настройки тоже можно задать при регистрации.
• Именованный: CreateClient("github") возвращает клиент с настройками конкретного API.
• Типизированный: GitHubClient получает настроенный HttpClient через DI и скрывает детали HTTP за методами сервиса.

Например, именованный клиент:


services.AddHttpClient("github", client =>
{
client.BaseAddress = new Uri("https://api.github.com/");
client.DefaultRequestHeaders.UserAgent.ParseAdd("MyApp/1.0");
});

// При использовании:
using var client = factory.CreateClient("github");


Нюанс: типизированный клиент не стоит надолго удерживать в singleton без настройки обновления соединений.

Фабрика также не единственный правильный вариант: Microsoft рекомендует и долгоживущий HttpClient с настроенным PooledConnectionLifetime. Главное: управлять временем жизни соединений.
🔥 Хочешь быстрее расти в IT? Хватит учиться в одиночку

Окружение решает больше, чем кажется.

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

AI: t.me/ai_machinelearning_big_data
Python: t.me/pythonl
Linux: t.me/linuxacademiya
Хакинг: t.me/linuxkalii
DevOps: t.me/DevOPSitsec
Docker: https://t.me/+90Z5TAyfuNU5YmRi
Golang: t.me/Golang_google
Rust: t.me/rust_code
C++: t.me/cpluspluc
C#: t.me/csharp_1001_notes
Java: t.me/javatg
JavaScript: t.me/javascriptv
React: t.me/react_tg
Frontend: t.me/front
PHP: t.me/phpshka
Android: t.me/android_its
Мобильная разработка: t.me/mobdevelop
Базы данных: t.me/sqlhub
Data Science: t.me/data_analysis_ml
Big Data: t.me/bigdatai
Математика: t.me/data_math
Физика: t.me/fizmat
Kubernetes: t.me/kubernetc
GameDev: https://t.me/gamedev
Haskell: t.me/haskell_tg

Собеседования и карьера:

DS собеседования: t.me/machinelearning_interview
Python собеседования: t.me/python_job_interview

Папка с вакансиями: t.me/addlist/_zyy_jQ_QUsyM2Vi
Папка Go разработчика: t.me/addlist/MUtJEeJSxeY2YTFi
Папка Python разработчика: t.me/addlist/eEPya-HF6mkxMGIy
Папка ML: https://t.me/addlist/2Ls-snqEeytkMDgy
Папка Frontend: https://t.me/addlist/mzMMG3RPZhY2M2Iy

Полезное сверху:

ИТ-мемы: t.me/memes_prog
Английский для программистов: t.me/english_forprogrammers
ИИ и технологии: t.me/vistehno
954 ГБ open-source курсов: https://t.me/+rKBQEMccAA01MTcy
ИТ-книги бесплатно: https://t.me/addlist/BkskQciUW_FhNjEy

Max Ai: https://max.ru/ai_machinelearning_big_data
Max python: https://max.ru/pythonl
ТЕХНО: https://max.ru/vistehno
Max Go: https://max.ru/Golang_google
Max Linux: https://max.ru/linuxkalii
Devops: https://max.ru/DevOPSitsec
C#: https://max.ru/csharp_ci
C++: https://max.ru/cpluspluc
SQL: https://max.ru/sqlhub
Java: https://max.ru/javatg

Подписывайся на нужные направления и собирай себе ленту, которая реально двигает вперёд.
⚡ Где тормозит .NET-приложение? SharpLsp покажет прямо в VS Code

В SharpLsp есть встроенный профилировщик CPU и памяти для C# и F#. Подключаешься к уже работающему процессу и смотришь, на что приложение тратит ресурсы. Перезапускать и пересобирать его не нужно.

После сбора CPU-профиля расширение подсвечивает горячие строки кода, строит flame graph и показывает функции, которые занимают больше всего процессорного времени.

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

Отдельно устанавливать `dotnet-trace` не требуется. Движку профилировщика нужен runtime .NET 8 или новее, а у целевого процесса должна быть включена диагностика.

Проект открытый, под лицензией MIT, работает на Windows, macOS и Linux.

https://sharplsp.dev/blog/dotnet-profiler-vs-code-csharp-fsharp/
🧩 C# с подвохом: одна переменная — сколько запросов к БД?

В базе есть просроченные заказы. db.Orders — это DbSet<Order> в EF Core, а NotifyAsync к базе не обращается.


IEnumerable<Order> late = db.Orders
.Where(o => o.DueDate < today);

if (late.Any())
{
logger.LogWarning(
"{Count} late orders",
late.Count()
);

foreach (var order in late)
{
await notifier.NotifyAsync(order);
}
}


Сколько раз код обратится к базе и где будет выполняться подсчёт — в SQL или в памяти приложения?

Обратите внимание на тип late в первой строке. И изменится ли поведение, если заменить IEnumerable<Order> на var?

👇 Пишите ответ с объяснением.
🔐 «Не одобряй собственные расходы» — такое правило нужно проверять на сервере

Тайсир Джуде показывает, как защитить MCP-сервер на ASP.NET Core через Microsoft Entra ID.

На примере приложения для учёта расходов автор разбирает:

• Регистрацию сервера и клиента в Entra ID.
• Вход пользователя и проверку JWT-токенов.
• Разницу между scope - разрешением приложению действовать от имени пользователя — и ролью, позволяющей одобрять расходы.
• Ограничение доступа к отдельным MCP-инструментам и фильтрацию списка доступных tools.

Самый показательный момент: пользователь с ролью согласующего может одобрить чужой отчёт, но свой сервер отклонит. Личность определяется по токену, а бизнес-правило проверяется в коде.

Модель выбирает, какой инструмент вызвать. Сервер решает, разрешено ли выполнить действие.

📖 https://bitoftech.net/2026/10/13/securing-mcp-server-microsoft-entra-id/

#aspnetcore #dotnet #mcp
«Ускорь этот C#-код» — полезнее просить ИИ вместе с инструкцией, как измерять результат.

BlazingFastDotnet — сборник приёмов оптимизации .NET 10 и 11, упакованный в SKILL.md для ИИ-агентов. Его можно читать и как обычный технический справочник.

Внутри:

- Поиск узких мест: dotnet-counters, dotnet-trace, Linux perf и анализ машинного кода JIT.
- Память и многопоточность: аллокации, GC, конкуренция за блокировки и false sharing.
- Настройка выполнения: ThreadPool, сокеты, JIT и параметры NativeAOT.
- Оптимизация C#: SIMD, работа со строками и ASP.NET Core.

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

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

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

https://github.com/EgorBo/BlazingFastDotnet