Темп выпуска релизов .NET продолжает ускоряться
Microsoft выпустила .NET 9 в ноябре 2024 года как релиз со стандартным сроком поддержки (STS), и темпы улучшений не думают замедляться. С более чем 7500 pull request'ами, влитыми в один только репозиторий dotnet/runtime, .NET 9 стал самым быстрым и функциональным релизом платформы на сегодняшний день.
Но «самый быстрый» — понятие абстрактное. Как разработчикам нам нужно знать: что реально изменилось, что делает наш код лучше и стоит ли обновляться?
Это руководство разбирает каждое значимое улучшение при переходе с .NET 8 на .NET 9 — от языковых возможностей C# 13 до прироста производительности среды выполнения, интеграции с AI и усовершенствований ASP.NET Core — чтобы вы могли принять обоснованное решение для своей команды.
C# 13: языковые возможности, которыми вы действительно будете пользоваться
C# 13 поставляется вместе с .NET 9 SDK и вводит несколько возможностей, сокращающих шаблонный код и повышающих безопасность:
Коллекции в params
Раньше params был ограничен массивами. C# 13 расширяет поддержку params на любой тип коллекции, реализующий IEnumerable<T> и имеющий метод Add — включая List<T>, Span<T> и ReadOnlySpan<T>. Это устраняет ненужные аллокации массивов при вызове методов с переменным числом аргументов.
Новый тип Lock и его семантика
Тип System.Threading.Lock заменяет традиционный шаблон lock (obj) { } выделенным типом, который распознаётся компилятором. Новое ключевое слово lock работает с объектами Lock, порождая более эффективный код с улучшенной поддержкой отладки.
Интерфейсы для ref struct
Типы ref struct теперь могут реализовывать интерфейсы и использоваться как аргументы типов в дженериках. Это открывает такие паттерны, как высокопроизводительные абстракции на основе span, ранее невозможные из-за ограничений типов.
Частичные свойства и индексаторы
Частичные свойства и индексаторы теперь разрешены в частичных типах, делая генераторы исходного кода более выразительными. Авторы библиотек могут объявлять частичные свойства в сгенерированном коде, тогда как реализации живут в пользовательском коде — паттерн, который значительно упрощает архитектуры на основе генераторов исходного кода.
Приоритет разрешения перегрузок
Авторы библиотек теперь могут обозначить одну перегрузку как предпочтительную над другими с помощью атрибута [OverloadResolutionPriority]. Это устраняет ошибки компилятора о неоднозначном вызове при добавлении новых перегрузок к существующим API без нарушения работы потребителей.
Неявный доступ к индексатору в инициализаторах объектов
Теперь можно использовать оператор ^ (индекс с конца) в инициализаторах объектов, что делает инициализацию коллекций более выразительной при заполнении с конца последовательности.
Производительность среды выполнения: важен каждый такт
История производительности .NET 9 построена на сотнях точечных улучшений, которые в совокупности проявляются в реальных приложениях. Вот ключевые моменты:
Динамическая PGO: теперь оптимизирует приведения типов и ветвления
Динамическая оптимизация на основе профилирования (PGO) — представленная в .NET 8 — теперь выходит за рамки виртуальной диспетчеризации и включает оптимизацию приведений типов. JIT отслеживает наиболее часто встречающиеся типы в операциях obj is T и (T)obj, а затем генерирует быстрые пути для этих типов. В микробенчмарках операции проверки типов выполняются до 4 раз быстрее на распространённых путях.
Оптимизация циклов: снижение силы и обратный отсчёт
JIT теперь выполняет снижение силы (strength reduction) для циклов итерации по массивам, преобразуя доступ по индексу в арифметику указателей. В сочетании с автоматическим обратным отсчётом (замена cmp + jl на единственный jns) плотные циклы теряют одну инструкцию на итерацию. Для циклов на горячих путях по крупным коллекциям это быстро накапливается.
Устранение проверок границ: умнее, чем когда-либо
Анализ проверок границ в JIT теперь обрабатывает ранее пропускавшиеся паттерны — обратную индексацию, сложные условия циклов и доступ на основе span, взаимодействующий с более ранними проверками длины. Меньше проверок границ означает более плотные циклы и меньше ветвлений, которые могут быть предсказаны неверно.
Сборка мусора: динамическая адаптация
Серверный GC теперь включает динамическую адаптацию к размеру приложения, включённую по умолчанию. GC подстраивает своё поведение под реальные паттерны использования памяти приложением, а не под фиксированные эвристики, сокращая время пауз для памятеёмких нагрузок без ущерба пропускной способности.
Векторизация и Arm64
Генерации кода для Arm64 уделено значительное внимание: расширенная SIMD-векторизация и более эффективное использование инструкций, специфичных для Arm. Для облачных нагрузок, работающих на процессорах Graviton или Ampere, это напрямую переводится в снижение затрат на вычисления.
ASP.NET Core 9: безопасность по умолчанию, скорость по замыслу
ASP.NET Core 9 делает улучшения безопасности автоматическими, одновременно поднимая планку производительности выше:
Встроенная генерация документов OpenAPI
Новый пакет Microsoft.AspNetCore.OpenApi обеспечивает встроенную генерацию документов OpenAPI без необходимости в Swashbuckle или NSwag. Метаданные из minimal API, контроллеров и аннотаций типов автоматически отражаются в сгенерированных спецификациях OpenAPI, снижая нагрузку от зависимостей и улучшая совместимость.
Отпечатки статических ресурсов
Оптимизация статических файлов (JavaScript, CSS) на этапах сборки и публикации теперь включает автоматическое версионирование по отпечаткам. Сброс кэша становится автоматическим, устраняя распространённый источник ошибок с устаревшими ресурсами.
Улучшения Blazor
Новые шаблоны Hybrid и Web App упрощают настройку проекта. Определение режима рендеринга компонентов улучшает отладку. Механизм переподключения для Blazor Server был переработан, обеспечивая пользователям более плавный опыт при обрыве сетевых соединений.
Расширение Native AOT
Поддержка компиляции с опережением (ahead-of-time) в ASP.NET Core была расширена, снижая задержку холодного старта и потребление памяти. Для контейнеризированных микросервисов Native AOT означает меньшие образы и более быстрое масштабирование.
Сертификат разработки HTTPS для Linux
Настройка доверенного сертификата разработки на Linux для HTTPS во время разработки теперь значительно проще — улучшение качества жизни для команд, работающих на рабочих станциях Linux.
Строительные блоки для AI: .NET становится нативным для AI
.NET 9 вводит единый слой абстракции для AI, позиционируя .NET как первоклассную платформу для приложений на базе AI:
Microsoft.Extensions.AI
Набор абстракций C# для взаимодействия с сервисами AI — малыми и большими языковыми моделями (SLM и LLM), эмбеддингами и векторными хранилищами. Эти пакеты предоставляют единообразную модель программирования независимо от того, вызываете ли вы OpenAI, Azure OpenAI или локальные модели через ONNX Runtime.
Tensor<T> и TensorPrimitives
Новый тип Tensor<T> обеспечивает эффективную работу с многомерными данными с нулевым копированием при взаимодействии с ML.NET, TorchSharp и ONNX Runtime. TensorPrimitives расширился с 40 до почти 200 SIMD-оптимизированных операций, охватывая числовые примитивы, необходимые для инференса и конструирования признаков.
ML.NET 4.0
ML.NET 4.0 приносит загрузку моделей ONNX как Stream, новую поддержку токенизаторов для моделей GPT, Llama, Phi и Bert, а также экспериментальные порты TorchSharp семейств моделей Llama и Phi. Если вы создаёте .NET-приложения, которым нужен инференс AI на устройстве или в процессе, именно этот релиз делает это практичным.
Библиотека токенизаторов
Библиотека Microsoft.ML.Tokenizers теперь из коробки поддерживает токенизаторы Tiktoken (GPT-3/4/4o/o1), Llama, CodeGen, Phi2 и Bert. Это необходимо для управления контекстными окнами, расчёта стоимости токенов и предобработки текста для локальных моделей.
EF Core 9: Cosmos DB и предкомпилированные запросы
Entity Framework Core 9 сосредоточен на двух областях: более глубокой интеграции с Azure Cosmos DB for NoSQL и подготовке почвы для компиляции с опережением:
- Провайдер Cosmos DB: значительные обновления NoSQL-провайдера, включая улучшенную трансляцию LINQ, поддержку иерархических ключей секционирования и более эффективное управление пропускной способностью.
- Предкомпилированные запросы: шаги к AOT-компилированным запросам, устраняющим накладные расходы на компиляцию запросов во время выполнения — критично для производительности холодного старта в бессерверных и контейнеризированных средах.
- Улучшения сложных типов: более качественная обработка владеемых сущностей и объектов-значений, сокращающая шаблонный код, необходимый для насыщенных доменных моделей.
.NET MAUI: производительность и интеграция с десктопом
.NET MAUI в .NET 9 отдаёт приоритет производительности и возможностям для десктопа:
- CollectionView и CarouselView получили новые, более производительные реализации на iOS и Mac Catalyst.
- HybridWebView упрощает встраивание контента React, Vue.js или Angular внутрь приложений MAUI.
- TitleBar — элемент управления для десктопных приложений Windows, обеспечивающий нативную настройку заголовка окна.
- Улучшения Native AOT и обрезки (trimming) уменьшают размер приложения и время запуска на мобильных устройствах.
.NET 8 против .NET 9: сравнение бок о бок
| Категория | .NET 8 | .NET 9 |
|---|---|---|
| Тип релиза | LTS (поддержка 3 года) | STS (поддержка 2 года) |
| Версия C# | C# 12 | C# 13 |
| Динамическая PGO | Виртуальная/интерфейсная диспетчеризация | Добавляет приведения, ветвления, профилирование целых чисел |
| Абстракции AI | Отсутствуют (только пакеты NuGet) | Microsoft.Extensions.AI, Tensor<T> |
| OpenAPI | Сторонний (Swashbuckle) | Встроенный Microsoft.AspNetCore.OpenApi |
| Режим GC | Фиксированный серверный/рабочей станции | Динамическая адаптация к размеру приложения |
| ref struct | Не может реализовывать интерфейсы | Может реализовывать интерфейсы, использоваться как аргумент дженерика |
| Оптимизация циклов | Базовое распознавание циклов | Снижение силы, обратный отсчёт |
| LINQ | Стандартные операторы | Добавляет CountBy, AggregateBy |
| Native AOT | Ограниченная поддержка ASP.NET | Расширенная поддержка ASP.NET |
Стоит ли обновляться?
Обновляйтесь немедленно, если:
- Вы запускаете чувствительные к производительности нагрузки и можете выиграть от оптимизаций JIT, GC и циклов.
- Вы создаёте функции на базе AI — одни только новые абстракции
Microsoft.Extensions.AIи поддержка токенизаторов оправдывают миграцию. - Вы разворачиваете на Arm64 (Graviton, Ampere) — улучшения генерации кода для Arm64 напрямую снижают облачные затраты.
- Вы сопровождаете библиотеки NuGet — возможности C# 13, такие как
[OverloadResolutionPriority]и частичные свойства, улучшают опыт создания библиотек.
Учитывайте график, если:
- Вам требуется поддержка LTS — .NET 8 остаётся поддерживаемым до ноября 2027 года. Если вашей организации нужен LTS для соответствия требованиям, планируйте вместо этого миграцию на .NET 10 (LTS), применяя .NET 9 для новых проектов.
- Вы зависите от сторонних пакетов, которые ещё не добавили таргеты .NET 9 — убедитесь, что ваши критические зависимости поддерживают
net9.0, прежде чем мигрировать.
Для пользователей nopCommerce и Umbraco:
- nopCommerce 4.90 нативно нацелен на .NET 9 — если вы на 4.80 или более ранней версии, обновление до 4.90 автоматически даёт вам все эти улучшения.
- Umbraco 14+ работает на .NET 9 — все 20+ плагинов Umbraco от SplatDev были перенесены и протестированы на совместимость с .NET 9.
Путь обновления: практический чек-лист
- Установите .NET 9 SDK: скачайте с dotnet.microsoft.com.
- Обновите целевой фреймворк: измените
<TargetFramework>net8.0</TargetFramework>на<TargetFramework>net9.0</TargetFramework>во всех файлах .csproj. - Обновите ссылки на пакеты: обновите все пакеты NuGet до их последних версий, поддерживающих .NET 9.
- Устраните критические изменения: просмотрите официальный список критических изменений — для большинства приложений затрагиваемая область невелика.
- Включите новые возможности: задайте
<LangVersion>13</LangVersion>, чтобы использовать возможности C# 13. - Запустите набор тестов: полное регрессионное тестирование по модульным, интеграционным и E2E-тестам.
- Замерьте производительность до и после: используйте BenchmarkDotNet, чтобы количественно оценить прирост производительности в вашей конкретной нагрузке.
Итог
.NET 9 — не революционный релиз, срывающий заголовки. Это тот вид релиза, который тихо делает всё лучше: ваши циклы выполняются с меньшим числом инструкций, ваши проверки типов попадают на быстрые пути, ваш GC адаптируется к вашему приложению, а спецификации API генерируются автоматически. Эти улучшения накапливаются в каждом HTTP-запросе, каждом запросе к базе данных, каждом цикле рендеринга Blazor.
Для команд, всё ещё сидящих на .NET 6 или .NET 7, кумулятивная разница между .NET 6 и .NET 9 драматична — прирост производительности на 20–40% на типичных нагрузках, модернизированный язык C#, встроенная интеграция с AI и оптимизированная под контейнеры среда выполнения.
В SplatDev мы разрабатываем на .NET с версии 1.0 в 2009 году. Мы видели, как платформа выросла из работавшей только под Windows в по-настоящему кросс-платформенную, из закрытого исходного кода в полностью открытый, из ориентированной только на предприятия в облачно-нативную. .NET 9 представляет собой самую функциональную версию платформы, с которой мы когда-либо работали, — и мы уже поставляем на ней рабочие нагрузки в продакшене.
Готовы обновить ваш стек .NET? SplatDev предоставляет услуги миграции .NET, оптимизации производительности и full-stack разработки — от nopCommerce и Umbraco до заказных корпоративных приложений.
Поговорить с нашей командой .NET
Или свяжитесь с нами напрямую: [email protected]