.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 — це те, чого ми просили роками.
Це зрілий, швидкий і неймовірно потужний реліз. Час оновлюватися!
20 коментарів
Додати коментар Підписатись на коментаріВідписатись від коментарівдякую за статтю, гарна робота все це освітити, але якось не чую того «грандіозного апдейта»
i think i dont need this for clean code best regards marcin scholke
but good to know and You can code this way if You want nobody steal Your code :)
Вы серьезно?
Це є з .net 5
для F#
🤦🤦♀️🤦♂️
нажаль, попри всі заяви майків шо всі 3 мови дотнета рівноціні, на практиці шарп вважається дефолт мовою.
багато хто взагалі не згадує про існування фаршу і бейсіка 🤷♂️
Про бейсік не варто i згадувать
для «дефолтнної мови» скіптинг був у mono, ще раніше, може років 15 тому.
не користалися? звісно, бо воно нах. нікому не потрібно було
а тепер — ба: Головна зміна в .NET 10!
ото ти старий!
Ну а якщо відкинути релігію і стереотипи, чого ще не хватає? Ну крім екосистеми різного роду бібліотек. Но чисто функціонально, не сильно відрізняється від
в плані розробки і запуску скриптів
шарп скрипти всеодно компілюються.
може бути проблема якшо в юзера немає прав запису.
пітон і яваскрит запустяться. дотнет — ні
та пофіг, це все вібувається під капотом, в гіршому випадку холодний старт буде гірший ніж у js, але не гірший ніж у пітона, але в любому випадку ним можна нехтувати, це не так важливо для скриптів.
та воно в якийсь temp в user profile компілиться, важко уявити що у юзера не буде прав, а якщо не буде, то не буде прав запускати рандомний js код тим більше
права можуть бути, а от місця вже ні 😉
але вцілому я згоден. скріпти на шарпі/фарші це добре.
та ваще насрать, ніхто це в здоровому глузді не робить на енвах окрім ділдів бумерів та наркоманів, вже давно білди ранаються в докері і заливається вже докер імейдж на енв. ото іще лазити на енв машину і туди щось заливати, вже забув коли таке робив, мать в14-му останній раз. зараз запушив коміт і запустився пайплайн автоматично що білдить та заливає код. хоч ажур девопс хоч гитхаб єкшен хоч гіт лаб. деплоймент то девопсяча робота.
ну напишіть скрипт, який відсилає alert, або лист, коли закінчилось місце на диску
або скрипт, який встановить dotnet під час деплою на нову ноду
я звісно писати не буду, але в чому принципіальна проблема написати таке?
бо це все частина девопсі, інфраструктурі та клауду і вона не залежно від платформи розробки. ніхто в здоровому глузді не тримає прод систему котра від дотнет\нод_модулів білда может вижрати диск і стопнути машину. це взагалі страшилки якісь, ліл.
так а в чому проблема? не важче ніж написати скрипт на пітоні який установить пітон на нову ноду, чи скрипт на js який установить nodejs )
Оце супер — файлові застосунки та лефт джойн не пройшло і 30 років!!! Усе інше (чисто по мові) в принципі пофік якось, сахарь звичайний, not great not terrible.