In this article we are going to discuss what's new in .NET 10 — the features that actually matter for day-to-day development, including C# 14 improvements, runtime performance, ASP.NET Core updates, and EF Core 10.
.NET 10 released on November 11, 2025 and it's a Long-Term Support release — supported until November 2028. That means three years of security patches and updates. If we're still on .NET 8 (the previous LTS) or .NET 9, this is a good time to start planning an upgrade.
This isn't just a "patch and performance fixes" release. C# 14 introduces some features we've been asking for since forever. The runtime is measurably faster without changing any code. AI integration is now built into the platform itself. And EF Core 10 has some genuinely useful query improvements.
Let's go through what's actually new and worth paying attention to.
This tutorial shows how to:
- Understand what's new in C# 14 — field-backed properties, extension types, null-conditional assignment
- See the runtime performance improvements in .NET 10
- Explore ASP.NET Core 10 updates — OpenAPI 3.1, Blazor improvements
- Use EF Core 10 new features — named query filters, LeftJoin/RightJoin, vector search
- Use the new file-based app model — run .cs files without a project
- Understand the built-in AI integration with Microsoft.Extensions.AI
Why .NET 10 Matters
Every year Microsoft releases a new .NET version. Some years the changes are incremental. .NET 10 feels bigger than that.
The centerpiece of the release is built-in AI support. Microsoft describes .NET 10 as a unified, intelligent platform that lets developers move seamlessly from simple AI integrations to sophisticated multi-agent systems. But even without touching any AI features, performance gains span runtime, JIT compilation, and memory management. Hardware acceleration now includes Intel AVX10.2 and Arm64 SVE optimizations, with improved loop inversion and stack allocation reducing garbage collection pauses.
For teams building production apps — the LTS status is the most important thing. Upgrade once, get three years of support. Don't chase .NET 9 (which was a standard-term release) and have to upgrade again quickly.
Step 1 : C# 14 — Field-Backed Properties
This is one of those features that looks small but saves real time. In C# 13 and below, when we wanted to add custom logic to a property setter while keeping an auto-generated backing field, we had to declare the field manually :
// Old way — we had to declare the backing field ourselves
private string _name = string.Empty;
public string Name
{
get => _name;
set => _name = value?.Trim() ?? string.Empty;
}
In C# 14, we use the field keyword to access the compiler-generated backing field directly :
// C# 14 — field keyword accesses the compiler-generated backing field
public string Name
{
get => field;
set => field = value?.Trim() ?? string.Empty;
}
public DateTime CreatedAt
{
get => field;
init => field = value == default ? DateTime.UtcNow : value;
}
No manual field declaration needed. Cleaner DTOs and model classes. Less boilerplate in record types.
Step 2 : C# 14 — Extension Types (Extension Blocks)
C# has had extension methods for years — static methods that look like instance methods. They're useful but limited. We couldn't add properties, operators, or private fields through extension methods.
C# 14 introduces extension blocks that let us add actual instance methods, properties, indexers, and operators to any type — including sealed classes and built-in types like string :
// C# 14 extension block
extension(string s)
{
// Extension property
public bool IsValidEmail => s.Contains('@') && s.Contains('.');
// Extension method
public string ToCamelCase()
{
if (string.IsNullOrEmpty(s)) return s;
return char.ToLower(s[0]) + s[1..];
}
// Extension property
public int WordCount => s.Split(' ',
StringSplitOptions.RemoveEmptyEntries).Length;
}
// Usage — reads like a native property
if (userEmail.IsValidEmail)
{
Console.WriteLine($"Word count: {"Hello World".WordCount}");
}
No more StringExtensions.IsValidEmail(email) scattered in static helper classes. The extension feels like it belongs on the type.
Static extension members are also supported :
extension(Order)
{
public static Order CreateDefault() => new()
{
Status = "Pending",
CreatedAt = DateTime.UtcNow
};
}
// Usage
var order = Order.CreateDefault();
Step 3 : C# 14 — Null-Conditional Assignment
How many times have we written this :
if (user != null)
{
user.LastSeen = DateTime.UtcNow;
}
C# 14 adds ??= style null-conditional assignment with ?.= :
// C# 14 — assign only if the object is not null
user?.LastSeen = DateTime.UtcNow;
user?.Status = "Active";
If user is null, the assignment is skipped entirely. No null check needed. Particularly useful in event handlers and initialization code where the target might not exist yet.
Step 4 : C# 14 — Run a .cs File Without a Project
This one is surprisingly useful for quick scripts and prototypes. In .NET 10 we can run a single .cs file without creating a project :
# Create a single file
echo 'Console.WriteLine("Hello .NET 10");' > hello.cs
# Run it directly — no .csproj needed
dotnet run hello.cs
For more useful scripts — calling an API, processing a file, a quick calculation :
// api-check.cs — no project file needed
using System.Net.Http;
using System.Net.Http.Json;
var client = new HttpClient();
var response = await client.GetFromJsonAsync<WeatherData>(
"https://api.example.com/weather"
);
Console.WriteLine($"Temperature: {response?.Temperature}°C");
record WeatherData(double Temperature, string Description);
Run with dotnet run api-check.cs. Great for automation scripts, DevOps tasks, and quick prototyping without the overhead of creating a full project.
Step 5 : Runtime Performance — Faster Without Code Changes
The .NET 10 runtime introduces improvements in JIT inlining, method devirtualization, and stack allocations. It also includes AVX10.2 support, NativeAOT enhancements, improved code generation for struct arguments, and enhanced loop inversion for better optimization.
In practical terms — we upgrade to .NET 10, recompile, and our app runs faster. No code changes required.
A few specific improvements worth knowing about :
NativeAOT is smaller and faster — Native AOT compiled apps in .NET 10 are much smaller. A minimal API compiled with Native AOT comes in under 5MB versus 18-25MB in .NET 8. Cold start times are significantly improved. For Azure Functions or container-based microservices, this matters.
Stack allocation for small arrays — Small fixed-size arrays are now allocated on the stack instead of the heap. Less garbage collection pressure, faster execution for code that creates many small arrays in loops.
Struct argument improvements — Struct members now go directly into CPU registers instead of memory. Less load/store operations for value types.
Step 6 : ASP.NET Core 10 — OpenAPI 3.1 and Minimal API Updates
The ASP.NET Core 10.0 release introduces several new features and enhancements, including Blazor improvements, OpenAPI enhancements, and minimal API updates.
Full OpenAPI 3.1 support — Previous versions supported OpenAPI 3.0. ASP.NET Core 10 supports OpenAPI 3.1 which aligns with JSON Schema draft 2020-12. Better nullable support, better schema composition, better tooling compatibility.
// OpenAPI generation in .NET 10
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddOpenApi(options =>
{
options.OpenApiVersion = OpenApiSpecVersion.OpenApi3_1;
});
var app = builder.Build();
app.MapOpenApi();
app.MapGet("/orders/{id}", (int id) => Results.Ok(new Order(id, "Pending")))
.WithName("GetOrder")
.WithOpenApi();
app.Run();
Passkey support for Identity — ASP.NET Core 10 Identity now supports passkeys (WebAuthn). Users can log in using fingerprint, face ID, or hardware key instead of a password. Adding passkey support to an existing Identity project is now much simpler.
Blazor improvements — WebAssembly preloading is now built in — the WASM runtime starts loading before the user navigates to a WASM component, reducing the loading wait. Form validation is also improved with better integration for custom validators.
Step 7 : EF Core 10 — What's New
EF Core 10 ships with .NET 10 and has several updates that make data access cleaner.
Named Query Filters — previously EF Core supported one global query filter per entity. In EF Core 10 we can have multiple named filters and disable specific ones per query :
// Define multiple named filters
modelBuilder.Entity<Blog>()
.HasQueryFilter("SoftDelete", b => !b.IsDeleted)
.HasQueryFilter("Tenant", b => b.TenantId == currentTenantId);
// Ignore only the soft delete filter — tenant filter still applies
var blogs = await context.Blogs
.IgnoreQueryFilters(["SoftDelete"])
.ToListAsync();
// Ignore all filters
var allBlogs = await context.Blogs
.IgnoreQueryFilters()
.ToListAsync();
This is much cleaner than the old single-filter approach for multi-tenant apps or apps with soft delete.
LeftJoin and RightJoin in LINQ — EF Core 10 adds native LeftJoin() and RightJoin() LINQ methods :
// EF Core 10 — native LeftJoin
var results = await context.Students
.LeftJoin(
context.Departments,
student => student.DepartmentId,
dept => dept.Id,
(student, dept) => new
{
student.Name,
Department = dept != null ? dept.Name : "No Department"
}
)
.ToListAsync();
Previously we had to use GroupJoin + SelectMany which was confusing for anyone who just wanted a LEFT JOIN. This is much more readable.
Vector search for AI workloads — EF Core 10 brings full support for the new vector data type and VECTOR_DISTANCE() function, enabling AI workloads like semantic search and RAG with SQL Server 2025 and Azure SQL Database.
// Store embeddings and query by similarity
var similarProducts = await context.Products
.OrderBy(p => EF.Functions.VectorDistance("cosine", p.Embedding, queryEmbedding))
.Take(10)
.ToListAsync();
For apps that do semantic search, recommendation systems, or RAG (Retrieval Augmented Generation), this is built right into EF Core now.
ExecuteUpdate with conditional updates — EF Core 10 allows conditional property updates in ExecuteUpdateAsync :
await context.Blogs.ExecuteUpdateAsync(s =>
{
s.SetProperty(b => b.Views, b => b.Views + 1);
if (nameChanged)
s.SetProperty(b => b.Name, newName);
});
Step 8 : Built-in AI Integration — Microsoft.Extensions.AI
.NET 10 ships with Microsoft.Extensions.AI — a standardized library for working with AI models from different providers through one consistent interface.
using Microsoft.Extensions.AI;
// Register an AI client — works with OpenAI, Azure OpenAI, Ollama, GitHub Models
builder.Services.AddChatClient(
new OpenAIClient("your-api-key")
.AsChatClient("gpt-4o")
);
In our service, inject IChatClient :
public class SupportService
{
private readonly IChatClient _chatClient;
public SupportService(IChatClient chatClient)
{
_chatClient = chatClient;
}
public async Task<string> GetAnswerAsync(string question)
{
var response = await _chatClient.CompleteAsync(question);
return response.Message.Text ?? string.Empty;
}
}
The IChatClient interface works identically regardless of whether the underlying model is from OpenAI, Azure OpenAI, Ollama running locally, or any other provider. Middleware, dependency injection, and telemetry all work the same way we're used to in .NET. Switching AI providers is just changing the registration — no code changes in our services.
Should We Upgrade Now
If we're on .NET 8 (LTS) — plan the upgrade. Both are LTS releases. .NET 8 support runs until November 2026 so there's time, but .NET 10 has real improvements worth moving to.
If we're on .NET 9 (Standard Term Support — ends May 2026) — upgrade sooner rather than later. .NET 9 support ends before .NET 8 support does.
If we're starting a new project today — start on .NET 10. Three years of LTS support, all the new features, and no migration needed later.
Summary
We learned what's new in .NET 10 and why it matters for our day-to-day development. We covered :
- C# 14 field-backed properties using the
fieldkeyword — no more manual backing field declarations - Extension blocks in C# 14 — add properties, methods, and operators to any type including sealed classes
- Null-conditional assignment with
?.=operator - Running a single .cs file without a project using
dotnet run file.cs - Runtime improvements — JIT enhancements, AVX10.2, NativeAOT smaller binaries, stack allocation for small arrays
- ASP.NET Core 10 — full OpenAPI 3.1 support, passkey identity, Blazor WASM preloading
- EF Core 10 — named query filters, native LeftJoin/RightJoin, vector search, conditional ExecuteUpdate
- Microsoft.Extensions.AI — unified IChatClient interface for working with AI models from any provider
.NET 10 is worth upgrading to. The C# 14 improvements alone reduce boilerplate noticeably. The performance gains come for free just by recompiling. And with three years of LTS support, it's a stable foundation for production apps.
I hope you like this article...
Happy coding! 🚀
0 Comments