What's new in .NET 6

.NET 6 delivers the final parts of the .NET unification plan that started with .NET 5. .NET 6 unifies the SDK, base libraries, and runtime across mobile, desktop, IoT, and cloud apps. In addition to this unification, the .NET 6 ecosystem offers:

  • Simplified development: Getting started is easy. New language features in C# 10 reduce the amount of code you need to write. And investments in the web stack and minimal APIs make it easy to quickly write smaller, faster microservices.

  • Better performance: .NET 6 is the fastest full stack web framework, which lowers compute costs if you're running in the cloud.

  • Ultimate productivity: .NET 6 and Visual Studio 2022 provide hot reload, new git tooling, intelligent code editing, robust diagnostics and testing tools, and better team collaboration.

.NET 6 will be supported for three years as a long-term support (LTS) release.

Preview features are disabled by default. They are also not supported for use in production and may be removed in a future version. The new RequiresPreviewFeaturesAttribute is used to annotate preview APIs, and a corresponding analyzer alerts you if you're using these preview APIs.

.NET 6 is supported by Visual Studio 2022 and later versions.

This article does not cover all of the new features of .NET 6. To see all of the new features, and for further information about the features listed in this article, see the Announcing .NET 6 blog post.

Performance

.NET 6 includes numerous performance improvements. This section lists some of the improvements—in FileStream, profile-guided optimization, and AOT compilation. For detailed information, see the Performance improvements in .NET 6 blog post.

FileStream

The System.IO.FileStream type has been rewritten for .NET 6 to provide better performance and reliability on Windows. Now, FileStream never blocks when created for asynchronous I/O on Windows. For more information, see the File IO improvements in .NET 6 blog post.

Profile-guided optimization

Profile-guided optimization (PGO) is where the JIT compiler generates optimized code in terms of the types and code paths that are most frequently used. .NET 6 introduces dynamic PGO. Dynamic PGO works hand-in-hand with tiered compilation to further optimize code based on additional instrumentation that's put in place during tier 0. Dynamic PGO is disabled by default, but you can enable it with the DOTNET_TieredPGO environment variable. For more information, see JIT performance improvements.

Crossgen2

.NET 6 introduces Crossgen2, the successor to Crossgen, which has been removed. Crossgen and Crossgen2 are tools that provide ahead-of-time (AOT) compilation to improve the startup time of an app. Crossgen2 is written in C# instead of C++, and can perform analysis and optimization that weren't possible with the previous version. For more information, see Conversation about Crossgen2.

Arm64 support

The .NET 6 release includes support for macOS Arm64 (or "Apple Silicon") and Windows Arm64 operating systems, for both native Arm64 execution and x64 emulation. In addition, the x64 and Arm64 .NET installers now install side by side. For more information, see .NET Support for macOS 11 and Windows 11 for Arm64 and x64.

Hot reload

Hot reload is a feature that lets you modify your app's source code and instantly apply those changes to your running app. The feature's purpose is to increase your productivity by avoiding app restarts between edits. Hot reload is available in Visual Studio 2022 and the dotnet watch command-line tool. Hot reload works with most types of .NET apps, and for C#, Visual Basic, and C++ source code. For more information, see the Hot reload blog post.

.NET MAUI

.NET Multi-platform App UI (.NET MAUI) is still in preview, with a release candidate coming in the first quarter of 2022 and general availability (GA) in the second quarter of 2022. .NET MAUI makes it possible to build native client apps for desktop and mobile operating systems with a single codebase. For more information, see the Update on .NET Multi-platform App UI blog post.

C# 10 and templates

C# 10 includes innovations such as global using directives, file-scoped namespace declarations, and record structs. For more information, see What's new in C# 10.

In concert with that work, the .NET SDK project templates for C# have been modernized to use some of the new language features:

By adding these new language features to the project templates, new code starts with the features enabled. However, existing code isn't affected when you upgrade to .NET 6. For more information about these template changes, see the .NET SDK: C# project templates modernized blog post.

F# and Visual Basic

F# 6 adds several improvements to the F# language and F# Interactive. For more information, see What's new in F# 6.

Visual Basic has improvements in the Visual Studio experience and Windows Forms project startup.

SDK Workloads

To keep the size of the .NET SDK smaller, some components have been placed in new, optional SDK workloads. These components include .NET MAUI and Blazor WebAssembly AOT. If you use Visual Studio, it will take care of installing any SDK workloads that you need. If you use the .NET CLI, you can manage workloads using the new dotnet workload commands:

Command Description
dotnet workload search Searches for available workloads.
dotnet workload install Installs a specified workload.
dotnet workload uninstall Removes a specified workload.
dotnet workload update Updates installed workloads.
dotnet workload repair Reinstalls all installed workloads to repair a broken installation.
dotnet workload list Lists installed workloads.

For more information, see Optional SDK workloads.

System.Text.Json APIs

Many improvements have been made in System.Text.Json in .NET 6, such that it is now an "industrial strength" serialization solution.

Source generator

.NET 6 adds a new source generator for System.Text.Json. Source generation works with JsonSerializer and can be configured in multiple ways. It can improve performance, reduce memory usage, and facilitate assembly trimming. For more information, see How to choose reflection or source generation in System.Text.Json and How to use source generation in System.Text.Json.

Writeable DOM

A new, writeable document object model (DOM) has been added, which supplements the pre-existing read-only DOM. The new API provides a lightweight serialization alternative for cases when use of plain old CLR object (POCO) types isn't possible. It also allows you to efficiently navigate to a subsection of a large JSON tree and read an array or deserialize a POCO from that subsection. The following new types have been added to support the writeable DOM:

For more information, see JSON DOM choices.

IAsyncEnumerable serialization

System.Text.Json now supports serialization and deserialization with IAsyncEnumerable<T> instances. Asynchronous serialization methods enumerate any IAsyncEnumerable<T> instances in an object graph and then serialize them as JSON arrays. For deserialization, the new method JsonSerializer.DeserializeAsyncEnumerable<TValue>(Stream, JsonSerializerOptions, CancellationToken) was added. For more information, see IAsyncEnumerable serialization.

Other new APIs

New serialization interfaces for validation and defaulting values:

For more information, see Callbacks.

New property ordering attribute:

New method to write "raw" JSON:

Synchronous serialization and deserialization to a stream:

New option to ignore an object when a reference cycle is detected during serialization:

For more information about serializing and deserializing with System.Text.Json, see JSON serialization and deserialization in .NET.

HTTP/3

.NET 6 includes preview support for HTTP/3, a new version of HTTP. HTTP/3 solves some existing functional and performance challenges by using a new underlying connection protocol called QUIC. QUIC establishes connections more quickly, and connections are independent of the IP address, allowing mobile clients to roam between Wi-fi and cellular networks. For more information, see Use HTTP/3 with HttpClient.

ASP.NET Core

ASP.NET Core includes improvements in minimal APIs, ahead-of-time (AOT) compilation for Blazor WebAssembly apps, and single-page apps. In addition, Blazor components can now be rendered from JavaScript and integrated with existing JavaScript based apps. For more information, see What's new in ASP.NET Core 6.

OpenTelemetry

.NET 6 brings improved support for OpenTelemetry, which is a collection of tools, APIs, and SDKs that help you analyze your software's performance and behavior. APIs in the System.Diagnostics.Metrics namespace implement the OpenTelemetry Metrics API specification. For example, there are four instrument classes to support different metrics scenarios. The instrument classes are:

Security

.NET 6 adds preview support for two key security mitigations: Control-flow Enforcement Technology (CET) and "write exclusive execute" (W^X).

CET is an Intel technology available in some newer Intel and AMD processors. It adds capabilities to the hardware that protect against some control-flow hijacking attacks. .NET 6 provides support for CET for Windows x64 apps, and you must explicitly enable it. For more information, see .NET 6 compatibility with Intel CET shadow stacks.

W^X is available all operating systems with .NET 6 but only enabled by default on Apple Silicon. W^X blocks the simplest attack path by disallowing memory pages to be writeable and executable at the same time.

IL trimming

Trimming of self-contained deployments is improved. In .NET 5, only unused assemblies were trimmed. .NET 6 adds trimming of unused types and members too. In addition, trim warnings, which alert you to places where trimming may remove code that's used at run time, are now enabled by default. For more information, see Trim self-contained deployments and executables.

Code analysis

The .NET 6 SDK includes a handful of new code analyzers that concern API compatibility, platform compatibility, trimming safety, use of span in string concatenation and splitting, faster string APIs, and faster collection APIs. For a full list of new (and removed) analyzers, see Analyzer releases - .NET 6.

Custom platform guards

The Platform compatibility analyzer recognizes the Is<Platform> methods in the OperatingSystem class, for example, OperatingSystem.IsWindows(), as platform guards. To allow for custom platform guards, .NET 6 introduces two new attributes that you can use to annotate fields, properties, or methods with a supported or unsupported platform name:

Windows Forms

Application.SetDefaultFont(Font) is a new method in .NET 6 that sets the default font across your application.

The templates for C# Windows Forms apps have been updated to support global using directives, file-scoped namespaces, and nullable reference types. In addition, they include application bootstrap code, which reduces boilerplate code and allows the Windows Forms designer to render the design surface in the preferred font. The bootstrap code is a call to ApplicationConfiguration.Initialize(), which is a source-generated method that emits calls to other configuration methods, such as Application.EnableVisualStyles(). Additionally, if you set a non-default font via the ApplicationDefaultFont MSBuild property, ApplicationConfiguration.Initialize() emits a call to SetDefaultFont(Font).

For more information, see the What's new in Windows Forms blog post.

Source build

The source tarball, which contains all the source for the .NET SDK, is now a product of the .NET SDK build. Other organizations, such as Red Hat, can build their own version of the SDK using this source tarball.

Target framework monikers

Additional OS-specific target framework monikers (TFMs) have been added for .NET 6, for example, net6.0-android, net6.0-ios, and net6.0-macos. For more information, see .NET 5+ OS-specific TFMs.

Generic math

In preview is the ability to use operators on generic types in .NET 6. .NET 6 introduces numerous interfaces that make use of C# 10's new preview feature, static abstract interface members. These interfaces correspond to different operators, for example, IAdditionOperators represents the + operator. The interfaces are available in the System.Runtime.Experimental NuGet package. For more information, see the Generic math blog post.

NuGet package validation

If you're a NuGet library developer, new package-validation tooling enables you to validate that your packages are consistent and well-formed. You can determine if:

  • There are any breaking changes across package versions.
  • The package has the same set of public APIs for all runtime-specific implementations.
  • There are any gaps for target-framework or runtime applicability.

For more information, see the Package Validation blog post.

Reflection APIs

.NET 6 introduces the following new APIs that inspect code and provide nullability information:

These APIs are useful for reflection-based tools and serializers.

Microsoft.Extensions APIs

Several extensions namespaces have improvements in .NET 6, as the following table shows.

Namespace Improvements
Microsoft.Extensions.DependencyInjection CreateAsyncScope lets you safely use a using statement for a service provider that registers an IAsyncDisposable service.
Microsoft.Extensions.Hosting New ConfigureHostOptions methods simplify application setup.
Microsoft.Extensions.Logging Microsoft.Extensions.Logging has a new source generator for performant logging APIs. The source generator is triggered if you add the new LoggerMessageAttribute to a partial logging method. At compile time, the generator generates the implementation of the partial method, which is typically faster at run time than existing logging solutions. For more information, see Compile-time logging source generation.

New LINQ APIs

Numerous LINQ methods have been added in .NET 6. Most of the new methods listed in the following table have equivalent methods in the System.Linq.Queryable type.

Method Description
Enumerable.TryGetNonEnumeratedCount<TSource>(IEnumerable<TSource>, Int32) Attempts to determine the number of elements in a sequence without forcing an enumeration.
Enumerable.Chunk<TSource>(IEnumerable<TSource>, Int32) Splits the elements of a sequence into chunks of a specified size.
Enumerable.MaxBy and Enumerable.MinBy Finds maximal or minimal elements using a key selector.
Enumerable.DistinctBy, Enumerable.ExceptBy, Enumerable.IntersectBy, and Enumerable.UnionBy These new variations of methods that perform set-based operations let you specify equality using a key selector function.
Enumerable.ElementAt<TSource>(IEnumerable<TSource>, Index) and Enumerable.ElementAtOrDefault<TSource>(IEnumerable<TSource>, Index) Accepts indexes counted from the beginning or end of the sequence—for example, Enumerable.Range(1, 10).ElementAt(^2) returns 9.
Enumerable.FirstOrDefault<TSource>(IEnumerable<TSource>, TSource) and Enumerable.FirstOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>, TSource)
Enumerable.LastOrDefault<TSource>(IEnumerable<TSource>, TSource) and Enumerable.LastOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>, TSource)
Enumerable.SingleOrDefault<TSource>(IEnumerable<TSource>, TSource) and Enumerable.SingleOrDefault<TSource>(IEnumerable<TSource>, Func<TSource,Boolean>, TSource)
New overloads let you specify a default value to use if the sequence is empty.
Enumerable.Max<TSource>(IEnumerable<TSource>, IComparer<TSource>) and Enumerable.Min<TSource>(IEnumerable<TSource>, IComparer<TSource>) New overloads let you specify a comparer.
Enumerable.Take<TSource>(IEnumerable<TSource>, Range) Accepts a Range argument to simplify taking a slice of a sequence—for example, you can use source.Take(2..7) instead of source.Take(7).Skip(2).
Enumerable.Zip<TFirst,TSecond,TThird>(IEnumerable<TFirst>, IEnumerable<TSecond>, IEnumerable<TThird>) Produces a sequence of tuples with elements from three specified sequences.

Date, time, and time zone improvements

The following two structs were added in .NET 6: System.DateOnly and System.TimeOnly. These represent the date part and the time part of a DateTime, respectively. DateOnly is useful for birthdays and anniversaries, and TimeOnly is useful for daily alarms and weekly business hours.

You can now use either Internet Assigned Numbers Authority (IANA) or Windows time zone IDs on any operating system that has time zone data installed. The TimeZoneInfo.FindSystemTimeZoneById(String) method has been updated to automatically convert its input from a Windows time zone to an IANA time zone (or vice versa) if the requested time zone is not found on the system. In addition, the new methods TryConvertIanaIdToWindowsId(String, String) and TryConvertWindowsIdToIanaId have been added for scenarios when you still need to manually convert from one time zone format to another.

There are a few other time zone improvements as well. For more information, see Date, Time, and Time Zone Enhancements in .NET 6.

PriorityQueue class

The new PriorityQueue<TElement,TPriority> class represents a collection of items that have both a value and a priority. Items are dequeued in increasing priority order—that is, the item with the lowest priority value is dequeued first. This class implements a min heap data structure.

See also