C# 1001 notes
6.68K subscribers
415 photos
14 videos
2 files
368 links
Регулярные короткие заметки по C# и .NET.

Просто о сложном для каждого.

admin - @haarrp
Download Telegram
«Ядро Windows NT во многом превосходит Linux», считает исследовательница Google и бывший реверс-инженер Microsoft Лори Кирк.

Её аргумент касается устройства системы: в NT ресурсы представлены объектами с правами доступа. В Linux контроль строится из нескольких механизмов, включая права файлов, ACL, capabilities и SELinux. По мнению Кирк, из-за этого труднее ответить на вопрос: что именно разрешено ИИ-агенту, которому дали доступ к системе?

Кирк считает, что ядро, спроектированное с нуля в 2026 году, скорее напоминало бы NT, чем Linux. Ей возражают: отдельные механизмы дают Linux гибкость, которая помогла ему стать основой серверов и контейнеров.

Это спор об архитектуре и управлении доступом, а не доказательство, что одна ОС безопаснее другой.

Источник: https://www.windowslatest.com/2026/09/26/google-researcher-explains-why-windows-nt-puts-linux-to-shame-and-imagines-an-alternate-history-where-it-won/
Задачка по C# 14: сколько раз вызовется Next()?


int calls = 0;
int Next() => ++calls;

Box? a = null;
Box b = new();

a?.Value = Next();
b?.Value = Next();
a?.Value += Next();
b?.Value += Next();

Console.WriteLine($"{calls} {b.Value}");

class Box
{
public int Value
{
get;
set => field = value * 10;
}
}


Варианты:


A) 4 120
😎 2 120
C) 2 30
D) Код не скомпилируется


Ответ: B) 2 120

Здесь сразу две фичи C# 14.

Первая: null-conditional assignment. Теперь
?. можно ставить слева от присваивания, в том числе составного. Главный подвох в том, что если объект слева равен null, правая часть вообще не вычисляется. Поэтому для a функция Next() ни разу не вызывается, и счётчик доходит только до 2, хотя вызовов в коде четыре.

Вторая: ключевое слово `field`. Геттер остаётся автоматическим, а сеттер умножает значение на 10, обращаясь к скрытому полю без ручного объявления.

Считаем по шагам:

```
b?.Value = Next() → Next() = 1, сохраняем 1 * 10 = 10
b?.Value += Next() → читаем 10, Next() = 2, 10 + 2 = 12, сохраняем 120
```

Бонусный подвох:
b?.Value++ уже не скомпилируется. Составное присваивание с ?. разрешено, а инкремент и декремент нет.
🔐 Как аутентифицировать SSE в ASP.NET Core?

SSE работает поверх обычного HTTP и поддерживает аутентификацию. Подвох в браузерном `EventSource`: он не позволяет задать заголовок Authorization.

В статье Paul Karam разобраны варианты:

• Cookies: браузер отправляет их автоматически для своего origin. Для другого нужны withCredentials: true и корректный CORS.
• Одноразовый короткоживущий токен в URL: при переподключении придётся получить новый.
• `@microsoft/fetch-event-source`: позволяет передать Bearer-токен в заголовке.
• `HttpClient`: вариант для .NET-клиентов с обычными заголовками аутентификации.

Долгоживущий access token в URL может утечь через логи сервера или прокси. На сервере SSE-эндпоинт защищается стандартными средствами ASP.NET Core, например .RequireAuthorization() при cookie-аутентификации.

https://tiger4589.github.io/2026/10/02/sse-with-authentication.html
🔐 Passkeys можно использовать как второй фактор в ASP.NET Core.

Пользователь вводит пароль, затем подтверждает вход через Touch ID, Windows Hello или аппаратный ключ. Без SMS и шестизначных кодов.

Маартен Баллиау показал реализацию на ASP.NET Core Identity в .NET 10: провайдер второго фактора, временная cookie и два эндпоинта для запроса и проверки passkey.

Есть важный нюанс: `PasskeySignInAsync()` выполняет прямой вход и обходит отдельный этап 2FA. Поэтому в таком сценарии нужно проверить, что passkey принадлежит именно пользователю, который уже прошёл проверку пароля.

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

https://blog.maartenballiauw.be/posts/2026-10-01-using-aspnet-core-passkeys-for-second-factor-authentication/
Forwarded from C# (C Sharp) programming
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
🛠 У .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/
В C# наконец появились union-типы

Разбираем C# 15 и .NET 11: union-типы, закрытые иерархии через closed, аргументы в коллекционных выражениях, extension-индексаторы и именованные break и continue.

Разработчики на C# просили размеченные объединения (discriminated unions) почти десять лет. Обсуждение в репозитории языка годами оставалось одним из самых популярных, а команды тем временем писали свои OneOf, Result и иерархии из абстрактных record с бесконечными default: throw. В C# 15, который выходит вместе с .NET 11, союзы наконец становятся частью языка. Вместе с ними приходят закрытые иерархии, аргументы в коллекционных выражениях, extension-индексаторы и именованные break/continue. Разберём, что из этого реально пригодится в коде уже сейчас.

https://uproger.com/csharp-15-union-types/
CBOR в .NET – компактный бинарный формат для случаев, когда JSON становится слишком расточительным.

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

Формат сам описывает типы значений: для чтения не требуется заранее согласованный `.proto`-файл, как у Protobuf.

В .NET используется пакет:


dotnet add package System.Formats.Cbor


Запишем аналог {"age":8}:


using System.Formats.Cbor;

var writer = new CborWriter();
writer.WriteStartMap(1);
writer.WriteTextString("age");
writer.WriteInt32(8);
writer.WriteEndMap();

byte[] data = writer.Encode();
Console.WriteLine(Convert.ToHexString(data));
// A16361676508


6 байт вместо 9 байт JSON в UTF-8. Выигрыш зависит от данных: для текста разница может быть небольшой.

Обратное чтение:


var reader = new CborReader(data);
reader.ReadStartMap();
string key = reader.ReadTextString();
int age = reader.ReadInt32();
reader.ReadEndMap();


Подвох: System.Formats.Cbor предоставляет низкоуровневые reader/writer API. Автоматической сериализации произвольных объектов через Serialize<T>() здесь нет.

Эндрю Лок разбирает устройство формата, сравнение с JSON и Protobuf и пример его использования внутри ASP.NET Core.

https://andrewlock.net/an-introduction-to-compact-binary-object-notation-in-dotnet/
Microsoft экстренно обновила .NET. Предыдущие патчи закрыли уязвимости не полностью

Microsoft выпустила внеплановые обновления безопасности для .NET 8, 9, 10 и 11 RC3. Причина - несколько уязвимостей, включая опасную ошибку при распаковке Brotli.

Что обнаружили:

- CVE-2026-111497 - переполнение буфера в Brotli. Злоумышленник потенциально может читать или повреждать память процесса, вызывать сбои и повышать привилегии.
- CVE-2026-114148 - небезопасные права владения файлами в Linux-дистрибутивах .NET.
- CVE-2026-70197 - повреждение памяти при работе с SocketAsyncEventArgs.
- CVE-2026-102870 - уязвимость отладчика Blazor WebAssembly.

Последние две особенно интересны: патчи от 13 октября не устранили проблемы полностью. Microsoft пришлось выпускать исправления повторно.

Обновлённые версии:

- .NET 8 → 8.0.33
- .NET 9 → 9.0.22
- .NET 10 → 10.0.14
- .NET 11 → RC3

Проверить установленный runtime:


dotnet --list-runtimes


Нюанс для DevOps: если приложение опубликовано как self-contained или работает в Docker, обновления runtime на хосте недостаточно. Потребуется пересборка и повторный деплой.

Особое внимание приложениям, которые обрабатывают недоверенные Brotli-сжатые данные через ASP.NET Core, HttpClient или System.IO.Compression.

https://devblogs.microsoft.com/dotnet/dotnet-october-2026-oob-security-updates/
Microsoft представит .NET 11 уже 10 ноября

С 10 по 13 ноября пройдёт .NET Conf 2026, бесплатная онлайн-конференция, приуроченная к выходу .NET 11.

Разработчики Microsoft расскажут, что изменилось в новой версии платформы, и покажут возможности обновлённого стека.

В программе C# 15, ASP.NET Core, Blazor, .NET MAUI, интеграция ИИ в .NET-приложения и обновления Visual Studio.

Будут технические доклады от команд Microsoft, демонстрации новых возможностей и выступления разработчиков из сообщества.

Участие бесплатное, всё проходит онлайн. Хорошая возможность разобраться в .NET 11 непосредственно с инженерами, которые его разрабатывают.

10–13 ноября 2026 года.

Программа и регистрация: https://devblogs.microsoft.com/dotnet/get-ready-for-dotnet-conf-2026/