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

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

admin - @haarrp
Download Telegram
This media is not supported in your browser
VIEW IN TELEGRAM
🚀 Claude Opus 5 за 24 часа собрал собственный космический симулятор

Разработчик запустил модель на одну непрерывную сессию и получил The Long Silence - полноценную браузерную игру об исследовании космоса. По словам автора, весь код, визуал и звук создал Claude.

Внутри:

• процедурные звёзды, планеты, кольца и туманности
• посадка на поверхность планет
• перелёты между системами и fold drive
• сканирование объектов, станции и заброшенные корабли
• карта галактики, сюжет и архив найденных данных
• динамическое масштабирование графики для стабильных 60 FPS

Игра работает на WebGL2 без готовых ассетов: миры генерируются из seed, графика написана на GLSL, а музыка и звук создаются процедурно.

Это ещё не Starfield по масштабу, но для проекта, собранного моделью за сутки, результат выглядит безумно.

🎮 Код и запуск: https://github.com/achimala/TheLongSilence

🌐 Запустить в браузере: https://longsilence.anshu.dev/
🔥 EF Core migrations - это компилятор схемы базы, а не кнопка «создать таблицу»

Опытный C#-разработчик не оставляет бизнес-инварианты только внутри SaveChangesAsync().

Проверку в приложении можно обойти прямым SQL, импортом данных, фоновым процессом или второй версией сервиса. Поэтому правила, нарушение которых делает данные некорректными, стоит закреплять в самой базе.


public sealed class ProductConfiguration
: IEntityTypeConfiguration<Product>
{
public void Configure(EntityTypeBuilder<Product> builder)
{
builder.ToTable("Products", table =>
{
table.HasCheckConstraint(
"CK_Products_Price_Range",
"[Price] > 0 AND [Price] <= 10000000");
});

builder.Property(x => x.Name)
.HasMaxLength(200)
.IsRequired();

builder.Property(x => x.NormalizedName)
.HasMaxLength(200)
.IsRequired();

builder.Property(x => x.Price)
.HasPrecision(18, 2);

builder.HasIndex(x => x.NormalizedName)
.IsUnique()
.HasDatabaseName("UX_Products_NormalizedName");
}
}


HasPrecision(18, 2) управляет физическим представлением decimal, но не проверяет допустимый диапазон цены. За это отвечает CHECK.

Уникальный индекс решает другую важную проблему - гонку между запросами.


if (!await db.Products.AnyAsync(x => x.Name == name))
{
db.Products.Add(product);
await db.SaveChangesAsync();
}


Два параллельных запроса могут одновременно пройти AnyAsync() и попытаться создать одинаковые записи. Только уникальное ограничение базы гарантированно остановит второй запрос.

Использовать для уникальности исходный Name тоже опасно. Результат будет зависеть от collation базы: Laptop, LAPTOP и Laptop могут считаться одинаковыми или разными. Поэтому часто сохраняют нормализованное значение:


product.NormalizedName = product.Name
.Trim()
.ToUpperInvariant();


После изменения модели создаём миграцию:


dotnet ef migrations add HardenProductSchema


Но миграцию нельзя принимать вслепую. EF Core сравнивает текущую модель с ModelSnapshot и генерирует предполагаемый переход между двумя состояниями.

Например, обычное переименование свойства может быть распознано как удаление старого столбца и создание нового:


migrationBuilder.DropColumn(
name: "Name",
table: "Products");

migrationBuilder.AddColumn<string>(
name: "DisplayName",
table: "Products",
nullable: false);


В production это означает потерю данных. Правильную операцию нужно указать вручную:


migrationBuilder.RenameColumn(
name: "Name",
table: "Products",
newName: "DisplayName");


Для крупных таблиц полезен подход expand -> backfill -> contract.

Сначала добавляется nullable-столбец:


migrationBuilder.AddColumn<string>(
name: "NormalizedName",
table: "Products",
type: "nvarchar(200)",
nullable: true);


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

Так миграция не держит долгую блокировку и остаётся совместимой сразу с несколькими версиями приложения.

В CI стоит проверять, не забыл ли разработчик создать миграцию:


dotnet ef migrations has-pending-model-changes


Для production лучше генерировать проверяемый SQL:


dotnet ef migrations script \
--idempotent \
--output migrations.sql


Либо собирать отдельный executable:


dotnet ef migrations bundle \
--self-contained \
-r linux-x64


efbundle можно запускать в deployment job без исходников проекта и установленного EF CLI.
🚀 C# 15 меняет подход к `unsafe`: указатели больше не означают автоматически опасный код

Раньше в C# сам факт использования указателя требовал:


unsafe
{
int* ptr;
}


Теперь язык движется к более точной модели:

опасным считается не наличие указателя, а операция, которая реально работает с unmanaged-памятью.

В preview-версии C# 15 уже не требуют unsafe:

объявление pointer-типа
получение адреса через &
fixed для закрепления памяти
преобразование stackalloc в указатель
sizeof для unmanaged-типов

Пример:


int number = 42;

int* pointer = &number;

int[] numbers = [10, 20, 30];

fixed (int* first = numbers)
{
// само закрепление памяти безопасно
}


Но вот это всё ещё требует unsafe:


*pointer; // dereference
pointer->Value; // доступ через указатель
pointer[0]; // работа с элементами
delegate*<> // вызов function pointer


Главная идея:

**создать инструмент можно безопасно.
Опасно — когда начинаешь напрямую менять память.**

Это первый этап большой переработки модели безопасности C#.

Дальше ожидаются:

- requires-unsafe для отдельных членов;
- opt-in на уровне assembly;
- новый safe keyword.

C# постепенно делает unsafe-код более точечным: меньше блоков вокруг всего файла, больше внимания к реально опасным операциям.

#csharp #dotnet #programming
⚡️ C#-приём: не привязывай метаданные к объектам через обычный `Dictionary` — иногда нужен `ConditionalWeakTable`.

Допустим, библиотека кеширует данные о типах:


private static readonly Dictionary<Type, Metadata> Cache = new();


В обычном приложении это может годами работать без проблем.

Но если используются plugins, dynamic assemblies или unloadable AssemblyLoadContext, такой словарь способен удерживать Type, а вместе с ним — всю загруженную сборку.

И получить memory leak.

Для таких случаев в .NET есть малоизвестный:


ConditionalWeakTable<TKey, TValue>


Пример:


private static readonly ConditionalWeakTable<Type, Metadata> Cache = new();

static Metadata GetMetadata(Type type)
{
return Cache.GetValue(type, BuildMetadata);
}


Ключ здесь хранится слабо.

Если Type больше нигде не нужен, GC может его собрать, а связанная запись автоматически исчезнет из таблицы.

Это особенно полезно для:

* reflection-кешей;
* proxy/framework-кода;
* source/runtime metadata;
* plugin-систем;
* приложений с AssemblyLoadContext.

🔥 Если видишь:


static Dictionary<Type, ...>


или


static ConcurrentDictionary<Type, ...>


в коде, который работает с динамически загружаемыми сборками, стоит проверить:

не удерживает ли этот кеш сборки в памяти навсегда?

Иногда правильный ответ — ConditionalWeakTable.

#CSharp #DotNet #Backend #Programming #CLR
Rate Limiting и Throttling API в .NET

В ASP.NET Core есть встроенные механизмы, которые помогают защитить API от перегрузки и слишком частых запросов.

Можно ограничивать трафик:

— по IP
— по пользователю
— по endpoint
— по фиксированному окну
— через sliding window
— token bucket
— concurrency limiter

Это полезно не только против DDoS. Rate limiting помогает не дать одному клиенту забить весь сервис, защитить дорогие операции и стабилизировать нагрузку на БД и внешние API.

В .NET это можно настроить прямо в middleware без сторонних библиотек.

Хороший разбор с примерами:
https://tundehub.dev/rate-limiting-and-throttling-apis-in-net

#aspnetcore #dotnet
⚡️Актуальные темы .NET на DotNext 2026

В .NET одновременно происходит много интересного: C# получает новые возможности, .NET 10 меняет расклад между Native AOT и JIT, а в разработке появляются ИИ-агенты, которые берут на себя часть инженерной работы.
На DotNext 2026 разберем как вещи, которые происходят на уровне машинного кода, так и вполне прикладные вопросы архитектуры и разработки.

📅 25–26 сентября, Москва + online

Выбрали 8 тем из программы, среди которых не только доклады, но и хардкорный воркшоп, чтобы показать этот диапазон:

— как заставить Transactional Outbox одновременно быть строгим и параллельным;
— зачем ASP.NET Core модульный монолит и как собрать его без микросервисов;
— где Native AOT выигрывает у JIT в .NET 10;
— что происходит с циклами, inlining и bounds checks в C# и Go;
— как меняется SDLC, когда в команде появляются ИИ-агенты;
— что принесут discriminated unions в C# 15;
— как проектировать асинхронное взаимодействие в распределенных системах (воркшоп).

Все подробности — в карточках и на сайте конференции.

🌟По промокоду csharp1001notes — персональные билеты дешевле

Программа DotNext

Купить билет
Forwarded from Machinelearning
Media is too big
VIEW IN TELEGRAM
✔️ Hugging Face прощупывает интерес покупателей

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

По данным источников, сейчас компанию оценивают примерно в 1,3 млрд долларов, тогда как в 2023 году оценка доходила до 4,5 млрд, - за три года почти в три с половиной раза ниже.

Наиболее вероятными покупателями называют нынешних инвесторов Hugging Face - Google, Amazon, Nvidia, Intel и Salesforce.
bloomberg.com

✔️ Alibaba запустила видеогенератор Wan3.0

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

Alibaba целится в производство рекламы, коротких сериалов и музыкальных клипов. До официального запуска модель была в открытой бете.

Иностранцы получают доступ к API через Alibaba Cloud. Секунда видео стоит 10 центов в 720p и 20 центов в 1080p, то есть полный тридцатисекундный ролик в 1080p обойдется в 6 долларов.
reuters.com

✔️ Antigravity теперь управляется с телефона

Агентом можно рулить со смартфона или из браузера, ничего дополнительно не устанавливая. В интерфейсе видно сессии в реальном времени, туда же ставятся задачи и оттуда проверяются результаты.

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

Обновление раскатывают постепенно, первыми его получают подписчики Google AI Ultra.
antigravity.google

✔️ FDA впервые разрешило автономного робота для забора крови

Американский регулятор выдал разрешение по процедуре системе Aletta голландского стартапа Vitestro. Робот делает всю процедуру сам: накладывает жгут, дезинфицирует кожу, находит вену, вводит иглу, меняет пробирки, убирает расходники и заклеивает прокол.

Вены он ищет ближней инфракрасной съемкой, ультразвуком и допплерографией - ими же отличает вену от артерии. В клинических испытаниях на 1600 пациентах игла попадала с первой попытки в 94,5% случаев.

Aletta рассчитана на амбулаторный прием взрослых. Один оператор может вести сразу три таких аппарата.
fda.gov

✔️ В Южной Корее микроэлектроника догоняет медицину по конкурсу в ВУЗы

На фоне ИИ-бума корейские абитуриенты пошли в микроэлектронику. По данным Jongno Academy, частного центра подготовки к поступлению, средний проходной балл на профильные специальности в ведущих вузах дошел до 96,2. Медицинские факультеты, где конкурс исторически самый высокий в стране, держат 97,2.

Университеты вместе с Samsung Electronics и SK Hynix запускают целевые программы с гарантированным трудоустройством. А школьники, чтобы поступить на инженерные направления, все лето занимаются в специализированных центрах Сеула.
ft.com

@ai_machinelearning_big_data

#news #ai #ml
Please open Telegram to view this post
VIEW IN TELEGRAM
Race Conditions в ASP.NET Core - как они появляются и почему их сложно ловить

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

Внутри:

- откуда берутся race conditions
- почему проблема может проявляться нестабильно
- как воспроизвести конкурентный доступ
- какие ошибки возникают при работе с shared state
- как использовать синхронизацию и безопасные паттерны
- почему потокобезопасность важна даже в обычном web API

Полезно для .NET-разработчиков, которые работают с многопоточностью, shared state и высоконагруженными ASP.NET Core-приложениями.

https://telerik.com/blogs/understanding-race-conditions-aspnet-core
Как собрать production-ready CRUD на ASP.NET Core

Telerik разобрала не просто базовый CRUD, а структуру приложения, которую уже можно нормально развивать дальше.

В примере используются:

- ASP.NET Core Web API
- Entity Framework Core
- PostgreSQL
- DTO
- Service layer
- Repository pattern
- AutoMapper
- FluentValidation
- Swagger / OpenAPI

Отдельный акцент сделан на разделении ответственности.

Контроллеры не должны содержать бизнес-логику, работа с БД выносится отдельно, входные данные валидируются до выполнения операций, а DTO не дают напрямую светить наружу модели базы.

Также разбираются:

- создание и настройка проекта
- подключение PostgreSQL
- миграции EF Core
- CRUD endpoints
- обработка ошибок
- валидация
- mapping между entity и DTO
- организация структуры проекта

Хороший материал, если базовый CRUD уже умеешь писать, но хочешь привести проект к более нормальной production-структуре.

https://telerik.com/blogs/creating-production-ready-crud-application-aspnet-core

#aspnetcore #dotnet
Вышел Aspire 13.5 - обновление с упором на интерфейс и удобство повседневной разработки.

Что добавили:

- обновлённый Dashboard и новый дизайн aspire.dev
- фильтрацию логов и трассировок по тексту, времени и числам
- более понятные ошибки health-check
- загрузку файлов прямо через команды AppHost
- окна прогресса с возможностью отмены
- полноценный терминал прямо внутри Dashboard через WithTerminal()
- поддержку persistent volumes для Kubernetes
- работу с существующими Azure-ресурсами из других resource group, подписок и tenants
- установку Aspire CLI через Homebrew, WinGet, npm, Nix, mise и NuGet

Отдельно удобно, что теперь часть инфраструктурных настроек можно описывать прямо в AppHost на C# или TypeScript, без постоянного ухода в YAML.

https://devblogs.microsoft.com/aspire/whats-new-aspire-13-5/
Полноценный Lisp можно уместить всего в 99 строк C.

Внутри при этом:

- 21 примитив
- REPL
- сборщик мусора Cheney GC
- числа с плавающей точкой
- указатели
- типы значений

И всё это без `struct`-тегов, без внешних библиотек и без обычных динамических аллокаций для представления объектов.

Главный трюк - NaN boxing.

IEEE 754 оставляет много битов внутри специальных NaN-значений. Их можно использовать как скрытое хранилище:

- часть битов кодирует тип
- до 48 бит можно использовать под указатель
- обычные double при этом остаются обычными числами

В итоге одно 64-битное значение может представлять и число, и указатель, и другие типы данных.

Очень красивый пример того, как устройство IEEE 754 можно использовать для построения компактного рантайма языка.
.NET и Владимир: отличный повод совместить митап и выходные в городе с историей

Офлайн-мероприятий для .NET-разработчиков сейчас не так много, а тут получается приятное комбо: встреча с другими разработчиками вечером в пятницу и возможность остаться на выходные в городе с историей.

В программе доклады от разработчиков Altenar и Рови Тех (часть Т-Банка):
— Async/await — асинхронность, которую можно читать.
— Как не терять данные при асинхронной интеграции программных систем.
— EF Core + PostgreSQL: за рамками CRUD.


Кстати, ещё на митапе запланированы активности для программистов: адаптации известных игр ("Сапер", "Крестики-нолики", "Гонки"), где для победы понадобится понимание математики и вероятностей.

Участие бесплатное, а ещё можно сэкономить на проезде — организаторы разыграют несколько билетов на "Ласточку" среди участников.

Для участия в розыгрыше:
1. Зарегистрируйтесь на митап.
2. Напишите «Хочу на .NET-митап на Ласточке» на почту aleksei.korneev@altenar.com с почты, указанной при регистрации.

Итоги розыгрыша подведём 14 сентября.


Регистрируйтесь, планируйте поездку и до встречи во Владимире!
Forwarded from C# (C Sharp) programming
✔️ Polly становится платной, но у .NET остаётся бесплатная альтернатива

Polly много лет была одной из главных библиотек .NET для устойчивости к временным сбоям: retry, timeout, fallback, rate limiting и circuit breaker.

Теперь Polly движется в сторону платной модели, но Microsoft.Resilience по-прежнему можно использовать бесплатно.

С .NET 8 работа с resilience стала заметно проще: появился новый API Polly и официальные библиотеки Microsoft для построения resilience pipelines.

Что можно настроить:

- Retry
- Fallback
- Timeout
- Rate limiting
- Circuit breaker

Хороший разбор того, как собирать устойчивые cloud-приложения на современном .NET:

https://milanjovanovic.tech/blog/building-resilient-cloud-applications-with-dotnet
Please open Telegram to view this post
VIEW IN TELEGRAM
⚡️ Задачи с технических собеседований в одном репозитории

Tech-OA-Interview-Questions - подборка задач из онлайн-тестирований и интервью в технологических компаниях. Пригодится для подготовки к алгоритмическим этапам отбора.

OA, или Online Assessment, - тестирование, которое кандидат обычно проходит перед собеседованиями. В репозитории собраны материалы для подготовки к таким заданиям, в том числе к отбору в Amazon.

Можно использовать как список для практики: решать задачи с таймером, оценивать сложность решения и проверять граничные случаи.

https://github.com/perixtar/Tech-OA-Interview-Questions
Согласны ?
🔧 Как передать многострочный PEM через Aspire в ASP.NET Core

Сертификаты и ключи в PEM содержат переносы строк, которые могут создавать проблемы при передаче через параметры Aspire. Damien Bod показал обходной вариант для локальной разработки с User Secrets и развёртывания в Azure.

Схема простая:

* закодировать PEM в однострочный Base64
* сохранить значение в конфигурации AppHost под ключом Parameters:ИмяПараметра
* объявить приватный ключ через AddParameter(..., secret: true)
* передать параметр приложению через WithEnvironment
* в ASP.NET Core декодировать Base64 обратно в исходный PEM

В статье есть helper-класс для преобразования, настройка AppHost и пример создания сертификата через X509Certificate2.CreateFromPem.

Base64 сохраняет переносы строк при передаче. Приватный ключ после кодирования остаётся секретом: Base64 не обеспечивает шифрование.

https://damienbod.com/2026/09/01/using-multiline-parameters-for-aspire-and-asp-net-core-with-user-secrets-and-azure-default-deployments/