.NET 9 is the latest and greatest version of .NET! It was released this November at .NET Conf 2024. Since then, we’ve had some time to dig into the new features and we’re excited to share our findings with you. While many new changes are being introduced, we’ve distilled this post down to the pieces that we think are the most useful and impactful.
What to expect with each .NET release:
- New version of C#
- ASP.NET Core Improvements
- EF Core Improvements
- Performance
- Visual Studio updates
- ... and more!
Support
.NET 9 is a Standard-Term Support (STS) version. STS releases stay in support for 18 months. While under support, you’ll receive security updates, support from Microsoft on any bugs or issues, and first-party support in Azure services. We often see companies opt for Long-Term Support (LTS) versions to upgrade, but do what’s best for you. We’ll talk about upgrade considerations later in this post.
C# 13
While C# 12 came with many bits of syntactic sugar, C# 13 is a little more reserved. It’s possible that the updates made in this version won’t impact the kind of code you write. This release seems to be full of smaller updates that will enable larger-scale changes in the future. Each section will include links to the Microsoft Docs if you’d like to dig in further!
Params Collections
Up until this version of C#, when using the params keyword for method parameters, we’ve always needed to declare the params type using an array []. In C# 13, we can now utilize different collection types.
https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-13#params-codllections
Implicit Index Access at Object Initialization
This one’s a little odd but interesting, nonetheless. We can now initialize an array using implicit indexing... in the screenshot below you’ll see us initialize an array starting from the last index. We haven’t thought of a real-world use case for this yet, but you can do it now!
https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-13#implicit-index-access
ref struct Improvements
If you write a lot of business application code, you may not have used ref structs before. They are pretty neat and have a number of great performance use cases. In this release, ref structs gained the ability to be used as generic type arguments and the ability to implement interfaces. Probably not something you’ll utilize in your code every day, but library maintainers and Microsoft themselves are sure to put this new feature to work. That means we’ll get the added performance boost for free! Awesome!
https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-13#allows-ref-struct
https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-13#ref-struct-interfaces
Partial Members
We’ve had partial classes in .NET for a very long time. They’ve actually been around since C# 2.0 came out in 2005! New with C# 13, we can also declare partial members within those partial classes. This allows you to separate the initialization and implementation of a member into two separate files. Maybe it's not something you’ll use every day, but this functionality could have a lot of cool implications when it comes to source generators and AOT compilation.
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/partial-member
ASP.NET Core
Static asset delivery optimization
New middleware for handling static files “app.MapStaticAssets()” over “app.UseStaticFiles”. This new middleware will not only compress your static assets but also can add ETags for each resource that is based on the contents of your files. Particularly for JS and CSS this is handy as the browser will only redownload the file if the actual content has changed.
OpenAPI Support
The Swashbuckle / Swagger solution that .NET has included in project templates for the last few versions is no longer being maintained and Microsoft is moving to a different solution going forward. As an alternative, the team has pivoted to supporting OpenAPI out of the box. If you’d like to learn more about this decision, check out the GitHub issue linked below.
https://github.com/dotnet/aspnetcore/issues/54599
HybridCache
New HybridCache class is meant to replace both IMemoryCache and IDistributedCache. We like the implementation of GetOrCreateAsync as a more functional way to interface with the cache.
https://learn.microsoft.com/en-us/aspnet/core/performance/caching/hybrid?view=aspnetcore-9.0
Better Dev Exception Pages
The ASP.NET Core team has added many small quality-of-life features to the dev exception page. Things like general UI cleanup and usability are at the forefront of these changes. There are also some nice additions around routing and endpoints metadata included on the page.
More
EF Core
EF Core has a few small changes that you’ll need to look for and a few nice improvements that you’ll get for free. Either way, it’s good to be aware of the changes from version to version since many of our .NET apps utilize Entity Framework Core.
Breaking Changes
Calling “.ToString()” on nullable properties in LINQ will now always result in empty string. This is a sneaky subtle change that could introduce bugs, so be on the lookout!
Improved Query Pruning
Reduced amount of fields/tables queried when they are not necessary to produce the result being requested.
Primitive Collection Translation
Primitive collection operations are now translated using OPENJSON rather than IN with string literals in SQL Server.
More leverage of native SQL functions
GREATEST, LEAST, and EXISTS are used more in EF’s translation layer
More on EF Core
https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-9.0/breaking-changes
https://learn.microsoft.com/en-us/ef/core/what-is-new/ef-core-9.0/whatsnew
Performance
.NET continues to get faster and uses less memory in each release. .NET 9 is no different. This creates a big incentive to update now.
"Nevertheless, the sentiment remains: .NET 9 is an incredibly exciting release. More than 7,500 pull requests (PRs) have merged into dotnet/runtime in the last year, of which a significant percentage have touched on performance in one way, shape, or form" ~ Stephan Toub
A few notable highlights are:
📚 Less to 0 Memory Allocations with Span Usage
🚀 LINQ is 3 and 5x faster, no memory allocations in some cases
🎯 dynamic profile guided optimization (PGO)
If you want to dig in deep, check out his article on all the performance improvements
Visual Studio
Visual Studio received some nice features this year. When learning the new capabilities, we couldn’t help but ask “that wasn’t already in VS?”. Lots of small quality-of-life improvements that you’ll probably notice if you use VS every day.
Copy from the Error List
If you’ve tried copying from Visual Studio’s error list in the past, you’ve probably ended up slightly disappointed. Prior to this latest version, VS would copy the entire line of metadata for you. Moving forward, VS’s default Ctrl+C behavior is to copy just the error message. Nice!
Go to line anywhere in Code Search
For a long while, we’ve been able to Code Search (Ctrl+T) and get to the files we want to investigate. With the latest VS, we can now append a colon and a line number to navigate directly to a specific line. We think this will be particularly helpful when digging into stack traces.
Dock the Code Search Window
In the olden days, Code Search (Ctrl+T) would pop up in the top-right corner of your code window, like where the “Find” window appears. In the last few versions, the Visual Studio team decided to pop-out this window. While it would be a nice option, it hasn’t been our favorite default, and there hasn’t been any way to return to a similar docked experience. They improved this in the latest version, and we couldn’t be happier!
Copy between instances
If you’ve ever tried copying files amongst two separate instances of Visual Studio, you’ve probably been surprised at how difficult / impossible it is to do. That changes in this latest version. Copying between instances is now officially supported.
Multi-Project Launch Config
Visual Studio allows you to set multiple projects as startup projects. This means you can simply F5 and start multiple APIs, console apps, etc. This is an essential feature for some projects, but the issue is there has not been a good way to save the launch config. In this latest version, they’ve added the ability to save profiles for multiple project launch scenarios. This will greatly improve sharing amongst teams and consistency across devices.
More on Visual Studio
https://learn.microsoft.com/en-us/visualstudio/releases/2022/release-notes#17.12.0
Making you more productive with Visual Studio v17.12 - Visual Studio Blog
Aspire
There was a lot of content and excitement around .NET Aspire. They made it Generally Available in May 2024 and have 50,000 reported users already.
“Powerful tools, templates and packages for building observable, production-ready apps”
We are exploring this tool and look forward to using it with our projects
👩💻 Developer Focused Tooling - Ready to Use
Containers
Observability
Azure Function Support
📚 Different Release Cycle
Built-in Resiliency (Polly+)
It even comes with a dashboard
You can watch the What's New in .NET Aspire keynote and hear the info for yourself.
Summary – Should I upgrade?
.NET 9 is full of performance and security-minded upgrades. It is the best .NET yet and is fully production-ready. Some teams are understandably wary of upgrading to STS versions of .NET. Typically, the updates do not include a ton of features that devs will use day-to-day. On top of this, the 1.5-year support lifetime can feel very short. Having only a 6-month window after the release of .NET 10 next year to complete the upgrade off of .NET 9 could be daunting to some teams.
Our suggestion is to consider whether you will still be actively developing your current solution by November of 2025. If so, you may as well get a jump start on the upgrade now. It has never been easier to upgrade .NET versions and taking the upgrade one bite at a time is a great way to reap some early performance benefits. If the app you are working on rarely receives active development, you may opt to wait for .NET 10. Every team works a little differently, so be sure to evaluate your options and make the decision that makes the most sense for you.
If you need a helping hand, feel free to reach out and let us know! We have seen many successful .NET upgrades and know what to look out for along the way. Thanks for reading!