.NET 10 приїхав! Що нам привезли в новій LTS-ці та Visual Studio 2026
Що ж, дочекалися. Microsoft на .NET Conf 2025 офіційно викотила .NET 10. Це нова LTS-ка (версія з довгостроковою підтримкою), а отже, з нами вона надовго — підтримка триватиме три роки. Разом з нею випустили і Visual Studio 2026, яку обіцяють зробити нарешті швидшою та зручнішою.
Я пробігся по головних анонсах і технічних доповідях. І, чесно кажучи, цього разу змін дуже багато. Давайте дивитися.
C# 14: Нарешті знову цікаво!
Почнемо з мови. C# 14 — це, мабуть, один з найзначніших релізів за останній час.
1. Extension Members (Моя улюблена фіча)
Ми жили з extension-методами з C# 3.0. Це було корисно, але синтаксис завжди був трохи незграбним. Тепер це виглядає набагато чистіше.
Раніше ми писали так:
public static class StringExtensions
{
public static bool IsNullOrEmpty(this string value)
{
return string.IsNullOrEmpty(value);
}
}
Тепер можна групувати логіку в extension блок:
public static class StringExtensions
{
// Оголошуємо тип і "змінну" один раз
extension(string value)
{
public bool IsNullOrEmpty()
{
return string.IsNullOrEmpty(value);
}
public string Truncate(int maxLength)
{
if (string.IsNullOrEmpty(value) || value.Length <= maxLength)
return value;
return value.Substring(0, maxLength);
}
}
}
Але це ще не все! Тепер можна додавати extension-властивості. Це просто знахідка для читабельності коду. Наприклад, замість !items.Any():
public static class CollectionExtensions
{
extension<T>(IEnumerable<T> source)
{
public bool IsEmpty => !source.Any();
public bool HasItems => source.Any();
}
}
// І в коді:
if (orders.IsEmpty) // Як же цього не вистачало!
{
Console.WriteLine("No orders to process«);
}
Всередині extension блоку можна навіть оголошувати private поля для кешування. Це взагалі топ.
extension<T>(IEnumerable<T> source)
{
private List<T>? _materializedList;
public List<T> MaterializedList => _materializedList ??= source.ToList();
public bool IsEmpty => MaterializedList.Count == 0;
}
А ще завезли статичні extension-члени для фабричних методів. Можна буде писати Product.CreateDefault() замість new Product(...) у коді. Дуже круто.
2. Ключове слово field
Нарешті нам не потрібно оголошувати _backingField вручну!
Раніше:
public class Record
{
private string _msg;
public string Message
{
get => _msg;
set => _msg = value ?? throw new ArgumentNullException(nameof(value));
}
}
Тепер:
public class Record
{
public string Message
{
get;
// "field" - це згенероване компілятором поле
set => field = value ?? throw new ArgumentNullException(nameof(value));
}
}
Це особливо зручно для лінивої ініціалізації:
public Dictionary<string, string> ConfigValues
{
// Ідеально для get-only властивостей з дефолтом
get => field ??= new Dictionary<string, string>();
set => field = value;
}
3. Null-Conditional Assignment
Про це я вже казав, але тепер це офіційно. Замість:
if (user is not null)
{
user.Profile = LoadProfile();
}
Пишемо:
user?.Profile = LoadProfile();
Дрібниця, а код чистить неймовірно.
4. Інші дрібні покращення
- Модифікатори в лямбдах: Тепер можна писати (text, out result) => ... без явного вказування типів (string text, out int result). Маленьке, але логічне покращення.
- Часткові (partial) конструктори та івенти: Це в основному для авторів source-генераторів, але дає їм більше гнучкості.
Головна зміна в .NET 10: «Файлові» застосунки
Ось це, як на мене, найбільша зміна в екосистемі. Вона повністю змінює підхід до скриптів та маленьких утиліт.
Раніше, щоб написати «Hello World», треба було:
dotnet new console- Отримати
sln,csprojіProgram.cs dotnet run
Тепер можна просто створити один файл main.cs і виконати:
dotnet run main.cs
Це ставить C# в один ряд з Python, JS та іншими скриптовими мовами. Написати утиліту для CI/CD чи автоматизації тепер можна без усього цього проектного «сміття».
Але як бути з пакетами? Дуже просто — через #: директиви:
// main.cs #:sdk Microsoft.NET.Sdk.Web #:package [email protected] using Microsoft.EntityFrameworkCore; var builder = WebApplication.CreateBuilder(); builder.Services.AddDbContext<OrderDbContext>(options => { options.UseSqlite("Data Source=orders.db"); }); var app = builder.Build(); app.MapGet("/orders", async (OrderDbContext db) => { return await db.Orders.ToListAsync(); }); app.Run(); // ... (визначення Order та OrderDbContext) ...
Ви тільки подивіться! Minimal API з EF Core в одному файлі! Це ж просто фантастика для прототипів. Можна посилатися і на існуючі проекти:
#:project ../ClassLib/ClassLib.csproj.
A для Unix-систем можна писати повноцінні shell-скрипти:
#!/usr/bin/env dotnet
Console.WriteLine("Hello from C# script!");
chmod +x app.cs ./app.cs
А коли ваш скрипт виросте, його можна легко конвертувати у повноцінний проект: dotnet project convert app.cs. Це дуже розумний хід.
ASP.NET Core 10
Тут теж багато хорошого.
- Вбудована валідація в Minimal APIs: Нарешті! builder.Services.AddValidation() — і ваші параметри та тіла запитів (включно з record) валідуються автоматично через DataAnnotations. Повертає 400 Bad Request, як і має бути. Це робить Minimal API ще на крок ближчими до повноцінних контролерів.
- Server-Sent Events (SSE): Це дуже крута альтернатива WebSockets, коли вам потрібен потік даних тільки від сервера до клієнта (наприклад, для дашбордів, оновлення цін). Реалізовано дуже чисто через IAsyncEnumerable<T> і TypedResults.ServerSentEvents.
- OpenAPI 3.1 та YAML: Підтримка OpenAPI 3.1 — це важливо для сумісності з JSON Schema. А можливість генерувати openapi.yaml замість JSON порадує багатьох фронтенд-розробників, бо YAML чистіший.
- JSON Patch: Додали підтримку JSON Patch для System.Text.Json.
EF Core 10
Тут дві головні фічі, і обидві довгоочікувані.
1. Комплексні типи (Complex Types)
Це, мабуть, головна фіча EF Core 10. Вона дозволяє моделювати дані, які є частиною сутності, але не мають власного ключа.
- Table Splitting: Ви можете зберігати ShippingAddress і BillingAddress як колонки в таблиці Customer (Street, City і т.д.).
- JSON Mapping: Або ж ви можете просто «запакувати» весь об’єкт Address в одну JSON-колонку в базі даних: b.ComplexProperty(c => c.ShippingAddress, c => c.ToJson());.
Це дає неймовірну гнучкість, дозволяючи поєднувати реляційний підхід із документо-орієнтованим. І так, це працює зі структурами (struct)!
2. Оператори LeftJoin та RightJoin
СТІЛЬКИ РОКІВ ЧЕКАНЬ! Більше ніяких страшних GroupJoin, SelectMany і DefaultIfEmpty для того, щоб зробити звичайний LEFT JOIN.
Тепер можна просто і зрозуміло написати:
var query = context.Students
.LeftJoin(
context.Departments,
student => student.DepartmentID,
department => department.ID,
(student, department) => new { /* ... */ });
Це просто свято для читабельності коду.
Blazor
Тут теж є приємні покращення:
- Hot Reload для Blazor WebAssembly (та .NET на WebAssembly).
- Профілювання продуктивності для WASM.
- Параметр NotFoundPage для роутера.
- Попереднє завантаження (preloading) статичних асетів у Blazor Web Apps.
Загалом, хороші QoL-покращення, особливо Hot Reload для WASM.
Під капотом: Перформанс і Runtime
Як завжди, .NET став ще швидшим.
- Постквантова криптографія: Це найцікавіше. В System.Security.Cryptography додали підтримку трьох постквантових алгоритмів
(ML-KEM, ML-DSA, SLH-DSA). Це інвестиція в майбутнє, щоб дані, зашифровані сьогодні, не можна було зламати квантовими комп’ютерами завтра. - Підтримка AVX10.2: .NET 10 вже готовий до нових процесорів, які з’являться наступного року.
- Масиви у стеку: JIT-компілятор тепер достатньо розумний, щоб малі масиви (навіть string[]) розміщувати в стеку. Це знижує навантаження на GC.
- Оптимізація GC та JIT-компілятора (кращий інлайнінг, менше навантаження).
Visual Studio 2026
Сама IDE теж отримала апгрейд. Обіцяють:
- Миттєвий запуск (на рівні VS Code).
- Оновлений, чистіший інтерфейс.
- Прискорення збірки до 25%.
- Покращений Hot Reload.
Вердикт
Якщо .NET 8 був солідним LTS, то .NET 10 — це просто величезний стрибок.
«Файлові» застосунки повністю змінюють правила гри для скриптингу. C# 14 з новими extension та field робить код набагато чистішим. А LeftJoin та «комплексні типи» в EF Core — це те, чого ми просили роками.
Це зрілий, швидкий і неймовірно потужний реліз. Час оновлюватися!
19 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарів