New Features in .NET 11 Preview 3: A Friendly Tour
A simple, beginner-friendly guide to .NET 11 Preview 3: C# 15 union types, runtime async, Zstandard compression, EF Core, MAUI maps, and more.
New Features in .NET 11 Preview 3: A Friendly Tour
Imagine your school just got a new water tap in the corridor. The old tap still works fine. But the new one is faster, wastes less water, and even tells you when the filter needs cleaning. You did not have to throw away the old tap to enjoy the new one. The new one simply makes every sip a little better.
A new .NET preview feels just like that new tap. Your old code still runs. But the team behind .NET keeps adding small, useful improvements that make daily coding smoother. In this post, we will take a calm, friendly walk through .NET 11 Preview 3. We will look at the new C# 15 union types, faster async, a new compression format called Zstandard, some Entity Framework Core help, and a few nice touches for .NET MAUI and web apps.
A quick, honest note first. A preview is a test version. It is perfect for learning and playing. It is not ready for your important, real-world apps yet. The final .NET 11 is planned for November 2026. So treat everything here as a peek into the future, not a tool for your exam-day project.
What is a preview, really?
Software is built in steps. The .NET team shows early versions so people can try them and give feedback. Each version is called a preview. Preview 1 comes first, then Preview 2, then Preview 3, and so on. By the time the final version ships, many small bugs have already been found and fixed by the community.
How a .NET version grows
Steps
Preview 1
First peek, early features
Preview 2
Union types arrive
Preview 3
Polish and more features
Release Candidate
Almost done, near-final
Final
Stable, safe for real apps
So .NET 11 Preview 3 is the third step on this path. It is more complete than Preview 1 and Preview 2, but still a few steps from the finish line.
The star of the show: C# 15 union types
This is the feature most people are talking about, so we will spend the most time here.
The everyday problem
Think about a parcel arriving at your home. It could be a letter, a box, or a tube. It is always exactly one of those three. It is never a letter and a box at the same time. And there is no fourth secret type hiding somewhere.
In older C#, saying "this value is exactly one of these few types" was clumsy. People used tricks, extra if checks, or outside libraries. It worked, but it was easy to forget a case and create a bug.
A union type solves this cleanly. A union says: "this value is exactly one of this fixed set of types." And the best part is that the compiler then forces you to handle every type. You cannot forget one by accident.
How a union looks in C# 15
The shipped C# 15 design composes the regular classes or records you already have. You do not invent brand-new inline types. Here is a small shape example.
// Your normal, everyday records:
public record Circle(double Radius);
public record Rectangle(double Width, double Height);
public record Triangle(double Base, double Height);
// A union that says: a Shape is exactly one of these three.
public union Shape(Circle, Rectangle, Triangle);That single union line ties the three records together. Now a Shape is always a Circle, a Rectangle, or a Triangle. Never two at once. Never something else.
The magic part: exhaustive matching
When you read a union with a switch, the compiler checks that you handle every case. If you forget one, the build fails with a clear error. You do not even need a catch-all default branch.
double Area(Shape shape) => shape switch
{
Circle c => Math.PI * c.Radius * c.Radius,
Rectangle r => r.Width * r.Height,
Triangle t => 0.5 * t.Base * t.Height,
// No default needed. The compiler knows all cases are covered.
};If a teammate later adds a Square to the union and forgets to update this method, the compiler will stop them. That is a friendly safety net. It turns a possible runtime crash into a clear message at build time.
The diagram below shows how the compiler thinks about a union.
Why this matters for you
Union types make a whole group of bugs simply disappear. Before, you might write code that handled two out of three cases and ship it. The third case would crash a user's app weeks later. With unions, that mistake cannot reach production. The compiler catches it first.
To try unions today, install the .NET 11 Preview SDK, target net11.0, and set <LangVersion>preview</LangVersion> in your project file.
<PropertyGroup>
<TargetFramework>net11.0</TargetFramework>
<LangVersion>preview</LangVersion>
</PropertyGroup>Here is a simple table comparing the old way and the new way.
| Question | Old C# (before unions) | C# 15 with unions |
|---|---|---|
| How do I say "one of these types"? | Tricks, extra libraries, or base classes | A simple union keyword |
| Who checks I handled every case? | Nobody, until it crashes | The compiler, at build time |
Do I need a default branch? | Usually yes, just to be safe | No, if you cover every case |
| When do I find a missing case? | Late, often in production | Early, while building |
Runtime async grows up
Now let us look under the hood. Most modern apps use async and await to do many things at once without freezing. Think of a waiter taking orders from many tables instead of standing still at one table.
In .NET 11, the team has been building a faster, cleaner way to run async code, called runtime async. The runtime itself handles the async work, instead of the compiler rewriting your method into a hidden state machine.
In Preview 3, a nice step happened: runtime async no longer needs the special preview features flag. Projects targeting net11.0 can turn on the runtime-async switch without also setting EnablePreviewFeatures to true. Support was also added for NativeAOT and ReadyToRun, two ways of getting apps to start faster.
Old async vs runtime async
Steps
Your async code
You write await as usual
Old way
Compiler builds a hidden machine
New way
Runtime does the work directly
Result
Lower overhead, clearer errors
The two big wins are cleaner stack traces (so error messages are easier to read when something breaks) and lower overhead (so your app does a tiny bit less work each time). You do not have to change how you write await. The improvement happens below your code.
Faster squeezing with Zstandard
When a web server sends data to your browser, it often compresses it first. Compression is like vacuum-packing a blanket so it takes less space in your bag. Smaller data means faster downloads and lower bills.
For years, .NET used GZip and Brotli for this. .NET 11 now natively supports Zstandard (often written zstd). It is a modern algorithm that is frequently faster than GZip or Brotli while keeping excellent compression. In some workloads it gives 2 to 7 times faster compression and up to 14 times faster decompression.
In ASP.NET Core, Zstandard response compression and request decompression are built in. The diagram below shows where compression sits in a normal web request.
For most web apps this means snappier pages with no extra code from you. For logging pipelines and big-data jobs, the speed gain can be even bigger. Here is a simple comparison of the common choices.
| Algorithm | Speed | Compression size | Good for |
|---|---|---|---|
| GZip | Medium | Good | Old, widely supported default |
| Brotli | Slower | Very good | Static web assets |
| Zstandard | Very fast | Very good | Web responses, logs, big data |
Entity Framework Core: less wasted work
If your app talks to a database, you likely use Entity Framework Core (EF Core). It keeps track of your data objects and notices when they change.
There is a step called change detection. EF Core scans your tracked objects to see what is new, what changed, and what was deleted. For a small app this is instant. For a big app tracking hundreds of objects, scanning over and over can slow down hot paths.
Preview 3 adds a new helper on the change tracker: GetEntriesForState. It returns the tracked entities in a chosen state without forcing a full scan first.
// Get only the entities that were added, without a full DetectChanges scan.
var newlyAdded = context.ChangeTracker.GetEntriesForState(EntityState.Added);
foreach (var entry in newlyAdded)
{
Console.WriteLine($"New entity: {entry.Entity}");
}This is a small, focused improvement. But in busy apps with large DbContext instances, skipping unneeded scans can save real time on the parts of your code that run most often.
Web and Blazor touches
The web side got some friendly upgrades too.
Kestrel, the web server inside ASP.NET Core, now begins processing HTTP/3 requests without waiting for the control stream to finish first. In plain words, the very first request on a fresh connection arrives a little sooner. New connections feel quicker.
Blazor's Virtualize component also got smarter. This component shows long lists without drawing every single row at once, which keeps the page light. Before, it assumed every row had the same height. Now it measures real sizes at runtime, so lists with rows of different heights look correct.
A nicer Map for .NET MAUI
.NET MAUI is the toolkit for building apps that run on phones and desktops from one codebase. Its Map control got several handy features in this release:
- Pin clustering, so many pins close together group into one neat marker instead of a messy pile.
- Custom pin icons, so you can use your own little pictures for places.
- Custom JSON styling, so you can change how the map looks.
- New click events for circles, polygons, and polylines, so tapping a shape can do something useful.
If you ever built a "find shops near me" screen, these features save a lot of fiddly work.
JIT improvements you get for free
The JIT (Just-In-Time compiler) turns your code into fast machine instructions while the app runs. Every release, the team teaches it new tricks. In Preview 3 it folds multi-target switch expressions into branchless checks, removes more redundant bounds checks on index-from-end access (like reading array[^1]), and speeds up some number conversions on older x86 hardware.
You do not change a line of code to enjoy these. You just rebuild on .NET 11 and your app runs a little faster. That is the quiet beauty of runtime work: free speed.
A quick word on libraries: MediatR and MassTransit
Many .NET teams use MediatR and MassTransit to organize messages between parts of an app. There is important news here that is easy to miss.
Both MediatR and MassTransit have moved to a commercial license. For small or learning projects they may still be free under their current license terms, but larger teams now need a paid plan. This has nothing to do with .NET 11 itself, but it matters when you plan a real project. Always read the current license before you add a library to production code. For learning, you can also explore the simpler built-in patterns first.
How the pieces fit together
Let us zoom out. Here is how the main Preview 3 features touch a typical app, from the code you write down to the user who sees the result.
Preview 3 features across an app
Steps
C# 15 code
Union types catch bugs early
Runtime async
Cleaner, lighter async
EF Core data
Less wasted scanning
Zstandard response
Smaller, faster downloads
Happy user
Quicker, more reliable app
Each feature is small on its own. Together they make the whole journey from your keyboard to the user a bit faster and a bit safer.
Should you try it now?
Yes, for learning. No, for real apps. Here is a simple way to decide.
- Try it on a hobby project, a study app, or a quick experiment with union types. This is the best way to learn.
- Wait before using it on a school competition entry, a client app, or anything people depend on. Previews can change, and bugs can hide.
- Plan ahead if you run a real project. Read the migration notes now, so the jump to the final .NET 11 in November 2026 is smooth.
To start, install the .NET 11 Preview 3 SDK, create a project that targets net11.0, and set <LangVersion>preview</LangVersion> if you want C# 15 features. Then build a tiny shapes app with union types. It is a fun, gentle first step.
Quick recap
- .NET 11 Preview 3 is a test version. Great for learning, not for shipping real apps. The final release is planned for November 2026.
- C# 15 union types let a value be exactly one of a fixed set of types, and the compiler checks that you handle every case. No more forgotten branches.
- Runtime async no longer needs the preview features flag and now supports NativeAOT and ReadyToRun. You get cleaner stack traces and lower overhead.
- Zstandard compression is built into ASP.NET Core, giving fast compression and very fast decompression.
- EF Core added
GetEntriesForStateto skip unneeded change-detection scans in busy apps. - Web and Blazor: faster first HTTP/3 requests, and a smarter
Virtualizethat measures real row heights. - .NET MAUI Map gained pin clustering, custom icons, custom JSON styling, and new shape click events.
- JIT got free speed-ups you enjoy just by rebuilding.
- Heads up: MediatR and MassTransit are now commercially licensed. Check the license before using them in real projects.
References and further reading
- .NET 11 Preview 3 is now available (.NET Blog)
- What's new in .NET 11 (Microsoft Learn)
- What's new in the .NET 11 runtime (Microsoft Learn)
- Explore union types in C# 15 (.NET Blog)
- Union types (C# reference, Microsoft Learn)
- Microsoft Releases .NET 11 Preview 3 (InfoQ)
- New Features in .NET 11 Preview 3 (antondevtips)