Finally! .NET 10 is just around the corner, so it's time to set off fireworks and celebrate the anniversary of our favorite platform! This article explores JIT improvements, the standard library expansions, new SDK capabilities, and other innovations.
.NET 10 focuses on enhancing performance and security—cryptography, in particular, has undergone significant refinement. This is a long-term support (LTS) release, meaning it will receive support for three years.
This article covers only some part of the important and interesting improvements in the libraries, Runtime, and SDK. A single post can't possibly detail all changes in the new .NET 10 anyway.
Our team is already working on supporting the new .NET 10 and C# 14—it will be available in PVS-Studio 7.40. The release is scheduled for early December. You're welcome to subscribe to our press release digest so as not to miss it.
C# 14
We have covered all innovations of C# 14 in another article. These include extension blocks, the field keyword, advancements in pattern matching, and much more. I should also note the support for the ? operator during assignment.
Before C# 14, we had to check a variable for null to safely assign a value to its property:
if (user is not null)
{
user.LastActive = DateTime.UtcNow;
}
Now, the equivalent code can look like this:
user?.LastActive = DateTime.UtcNow;
This innovation reduces boilerplate code, which is always a welcome change.
Performance
Each release makes our trusty .NET faster and faster. True to tradition, Stephen Toub has published an extensive article detailing performance improvements.
Specifically, the changes affect LINQ, regular expressions, cryptographic algorithms, JIT, AOT, I/O, and much more.
I recommend at least skimming the article to stay informed about all changes.
Libraries
Cryptography
The System.Security.Cryptography library now includes types to support three new asymmetric post-quantum algorithms: ML-KEM (FIPS 203), ML-DSA (FIPS 204), and SLH-DSA (FIPS 205).
.NET 10 is an LTS version, so adding support for post-quantum encryption algorithms is a very prudent decision, as the "harvest now, decrypt later" attack vector becomes more realistic each year. This scenario involves an attacker intercepting and storing encrypted data to decrypt it in the future when it becomes technically possible.
Collections
We now have additional overloads of TryAdd and TryGetValue methods for OrderedDictionary<TKey, TValue>. The only difference in the new methods is that they also return the index as an out parameter.
Serialization
We can now configure how to handle circular references during serialization or deserialization. We can do this by specifying the ReferenceHandler in the JsonSourceGenerationOptionsAttribute.
Now we also have the JsonSerializerOptiops.AllowDuplicateProperties parameter, which is needed to prevent the repetition of JSON properties.
Strings
.NET 10 introduces new APIs that extend normalization beyond string types. Existing APIs only worked with the string type, so data in other forms—such as character arrays or spans—had to be converted to a string. This is no longer necessary: the new APIs allow you to work directly with character ranges.
Methods have also been added for conversions between UTF-8 byte sequences and hexadecimal representations without the need to allocate intermediate strings. These methods overload the existing implementations that only work for string and ReadOnlySpan<char>, but they offer higher performance, working directly with UTF-8 encoded bytes.
Furthermore, the authors added the NumericOrdering option, which specifies that string comparison should be performed numerically rather than lexicographically. In this case, the "2" string will be equivalent to the "02" string.
Runtime
AVX10.2 support
The new framework version adds support for AVX10.2 instructions for x64-based processors. Keep in mind that processors supporting AVX10.2 will only be released next year, so we will only be able to fully test this new feature once the hardware is available.
Well, we're looking forward to the release!
Stack allocation for small arrays
.NET 10 introduces stack allocation for small arrays of both value and reference types. In this case, the array is allocated on the stack if the JIT is certain that the data won't outlive the context in which it was created. This change aims to reduce the number of objects the garbage collector needs to track. As a result, it reduces the load on the GC and opens up opportunities for future optimizations.
Look at the example:
static void Sum()
{
int[] numbers = {1, 2, 3};
int sum = 0;
for (int i = 0; i < numbers.Length; i++)
{
sum += numbers[i];
}
Console.WriteLine(sum);
}
The numbers array containing three integers will be allocated on the stack because the compiler knows this data lifecycle ends with the Sum method exit. The same applies to arrays of reference types.
static void Print()
{
string[] words = {"Hello", "World!"};
foreach (var str in words)
{
Console.WriteLine(str);
}
}
As in the previous example, the lifecycle of the words array is confined to the Print method, so the compiler places this array on the stack.
write-barrier GC
As you may know, the .NET garbage collector operates on a generational model, so the heap is managed according to how long objects have been in memory. This allows for quick collection of objects from specific generations. However, a problem occurs if a reference from a young generation somehow finds its way into an older generation—when scanning the young generation, the older ones aren't scanned.
To prevent such situations, a write barrier mechanism is used, which tracks cross-generational references.
Nevertheless, for compiler performance, the best write barrier is no write barrier at all.
.NET 10 also includes fixes that eliminate certain GC write barriers, which improves performance.
JIT improvements
.NET 10 brings significant enhancements to JIT compilation, all aimed at boosting performance. The changes include: improved inlining, better code generation for struct members, elimination of array enumeration abstraction, and much more.
SDK
Package reference removing
Starting with .NET 10, the NuGet audit feature can now remove references to unused packages. This innovation also focuses on optimization: it reduces the number of packages that need to be restored and analyzed during the build process.
This feature will be enabled by default for all project frameworks targeting .NET 10 and later versions.
MSBuild
MSBuild running in Visual Studio or via msbuild.exe is a .NET Framework application, whereas MSBuild running in the dotnet CLI is a .NET application. This means that any MSBuild tasks written for .NET can't be used when building in Visual Studio or when using msbuild.exe due to the environmental difference.
Starting with .NET 10, Visual Studio 2026 and msbuild.exe will run MSBuild tasks built for .NET. We can now use the same tasks whether building in Visual Studio or via msbuild.exe via the dotnet CLI. This change eliminates the need for redundant rewrites and ongoing maintenance of MSBuild tasks for different frameworks.
New commands
A new dotnet tool exec command allows us to execute a .NET tool without its installation globally or locally—this is especially useful for CI/CD.
Additionally, a new dnx script has been added, providing a simplified way to execute tools. It redirects all arguments to the dotnet command line interface for processing.
With the release of .NET 10, we can also inspect the command line interface using the --cli-schema parameter. When used, it outputs a JSON tree representation of the CLI commands for the invoked command or subcommand.
Running single C# files without projects
We can now create applications based on single files without a project, simplifying the program creation and execution. To do this, use the dotnet run command on a single *.cs file. According to the developers' idea, this approach will be useful for creating small command line utilities, prototypes, and various experiments.
All file-based applications target native AOT compilation by default and support publishing to native executables using dotnet publish.
Conclusion
In summary, we can confidently state that .NET 10 is a robust release, worthy of being both an anniversary edition and an LTS version. It's encouraging to see the developers consistently focusing on performance improvements and keeping the standard library up-to-date year after year.
This article has only highlighted some of the most notable innovations, in our opinion. You can review the full list of improvements here. Please comment below on any important or interesting changes I might have missed, as well as your thoughts on .NET 10—I look forward to reading them.
Now, let's all go celebrate the anniversary :)

Top comments (0)