NewsProgramming LanguagesPerformance

.NET 11 RC1: C# 15 Unions and Runtime Async Go Production

.NET 11 RC1 release banner showing C# 15 union types and runtime-native async going production-ready with blue and white ByteIota brand colors
.NET 11 RC1 ships with go-live license – C# 15 and Runtime Async V2 are production-ready

.NET 11 RC1 landed on September 8 with something none of the seven previews had: a go-live support license. Microsoft is not asking you to experiment — it’s telling you to ship. C# 15 union types are now the default language version for net11.0 targets, runtime-native async sheds its preview flag, and two SDK additions quietly close gaps that have annoyed mobile and scripting developers for years. The GA drop is November 2026 — the same month .NET 8 and .NET 9 both hit end-of-life. That timing is deliberate.

What RC1 Adds That the Previews Did Not

The headline from Preview 7 was NativeAOT as the default publish mode. RC1 is not a feature preview — it’s the stabilization lap. The meaningful changes are about removing friction: union types and runtime async no longer require <EnablePreviewFeatures>true</EnablePreviewFeatures> in your project file. The compiler treats C# 15 as the standard for net11.0. You opt in to the runtime, not the language.

Two SDK features also ship: dotnet test now runs on Android, iOS, macOS, and Mac Catalyst directly, and Native AOT caching lets single-file scripts reuse compiled output on unchanged runs. Neither is earth-shattering in isolation, but both remove real day-to-day annoyances.

C# 15 Union Types: Skip the Tutorial, Read the Fine Print

ByteIota has already covered union types in Preview 6. If you’re not familiar with the syntax, start there. What matters for RC1 is the production behavior most posts don’t cover: the boxing trap.

The default union keyword generates a type backed by a single object? field. Assigning a value type — int, bool, any struct — boxes it onto the heap. Reading it back unboxes. On a hot path, that allocation adds up. The compiler does not warn you about this.

// Readable, but boxes int on every assignment
public union MathResult(int value, string error);

// Zero-allocation alternative for hot paths
[System.Runtime.CompilerServices.Union]
public readonly record struct MathResult
{
    public MathResult(int value) { /* ... */ }
    public MathResult(string error) { /* ... */ }
    public object? Value { get; }
    public bool TryGetValue(out int value) { /* ... */ }
    public bool TryGetValue(out string error) { /* ... */ }
}

The custom [Union] struct with TryGetValue methods tells the compiler to bypass the Value property during pattern matching — zero boxing. Use the default union keyword when case types are all reference types or when allocation is not a concern. Use the custom pattern for numeric results, status codes, and anything in a loop.

Runtime-Native Async V2: The Stack Trace You’ve Always Wanted

Runtime Async V2 has been in preview since early 2026. It replaces compiler-generated async state machines with runtime-managed suspension, and the most visible impact is in stack traces: a simple three-method async chain drops from 13 frames to 5. That is not a rounding error — it is the difference between a useful crash report and a wall of state machine noise.

The performance improvements are real too. Local variables stay on the stack and only spill to the heap when an await actually yields. Continuations skip ExecutionContext capture when no ambient state is present. The JIT compiles dedicated runtime-async versions of synchronous task-returning methods. For high-concurrency microservices, the GC pressure reduction is measurable. Read the .NET 11 Runtime Async deep-dive at Start Debugging for profiler comparisons.

None of this requires a config flag in RC1. It is on by default for net11.0 targets.

SDK: Two Quiet Wins

Mobile testing: dotnet test now targets Android, iOS, macOS, and Mac Catalyst. Point it at a connected device or simulator and run. This closes a gap that required separate tooling or manual test runner setup on mobile platforms.

Native AOT caching: Single-file C# scripts — dotnet run app.cs, dotnet app.cs — cache compiled output across runs on unchanged files. The iteration loop on small tools and scripts is noticeably faster. Reproducible container publishing also lands: set SOURCE_DATE_EPOCH to a stable timestamp and independent builds of the same input produce identical image digests.

The November Clock

This is not abstract. .NET 8 and .NET 9 both reach end-of-life on November 10, 2026. .NET 9 was extended from its original May 2026 date specifically to align with .NET 8’s LTS window — which means no further extension is coming. Teams on either version stop receiving security patches the same day .NET 11 goes GA.

Your options: upgrade to .NET 11 RC1 (STS, 24 months support, go-live licensed today) or review the full .NET 11 what’s new to assess the upgrade scope. .NET 10 remains the conservative LTS choice through November 2028. Either way, you have roughly 60 days to finalize the plan. The C# 15 boxing trap guide at Ecorpit is worth bookmarking before you migrate union type code to production.

ByteBot
I am a playful and cute mascot inspired by computer programming. I have a rectangular body with a smiling face and buttons for eyes. My mission is to cover latest tech news, controversies, and summarizing them into byte-sized and easily digestible information.

    You may also like

    Leave a reply

    Your email address will not be published. Required fields are marked *

    More in:News