.NET 8 is a long-term support (LTS) release. .NET 8 is the successor to .NET 7. It will be supported for three years, in this article we will look into the enhancements and new features introduced with this release including C# 12, EF Core 8 and ASP.NET Core 8.0. Today it's still in preview (version 6), but you can download the SDK and play around from here.
Improvements to System.Text.Json
You can customize handling of members that aren't in the JSON payload: By default, if the JSON payload you're deserializing contains properties
that don't exist in the deserialized plain old CLR object (POCO) type,
they're simply ignored. Starting in .NET 8, you can specify that all
members must be present in the payload. If they're not, a JsonException exception is thrown.
The following code shows an example where the properties from both the immediately implemented interface and its base interface are serialized.
Core .NET libraries
The new TimeProvider class and ITimer interface add time abstraction functionality, which allows you to mock time in test scenarios. The time abstraction supports the following essential time operations:
- Retrieve local and UTC time
- Obtain a timestamp for measuring performance
- Create a timer
The following code snippet shows some usage examples.
GetItems<T>()
The new System.Random.GetItems and System.Security.Cryptography.RandomNumberGenerator.GetItems methods let you randomly choose a specified number of items from an input set. The following example shows how to use System.Random.GetItems<T>() (on the instance provided by the Random.Shared property) to randomly insert 31 items into an array.Shuffle<T>()
The new Random.Shuffle and RandomNumberGenerator.Shuffle<T>(Span<T>) methods let you randomize the order of a span. These methods are useful for reducing training bias in machine learning.Data validation
The System.ComponentModel.DataAnnotations namespace includes new data validation attributes intended for validation scenarios in cloud-native services. While the pre-existing DataAnnotations validators are geared towards typical UI data-entry validation, such as fields on a form, the new attributes are designed to validate non-user-entry data, such as configuration options. In addition to the new attributes, new properties were added to the RangeAttribute and RequiredAttribute types.New API | Description |
---|---|
RangeAttribute.MinimumIsExclusive RangeAttribute.MaximumIsExclusive | Specifies whether bounds are included in the allowable range. |
System.ComponentModel.DataAnnotations.LengthAttribute | Specifies both lower and upper bounds for strings or collections. For example, [Length(10, 20)] requires at least 10 elements and at most 20 elements in a collection. |
System.ComponentModel.DataAnnotations.Base64StringAttribute | Validates that a string is a valid Base64 representation. |
System.ComponentModel.DataAnnotations.AllowedValuesAttribute System.ComponentModel.DataAnnotations.DeniedValuesAttribute | Specify allow lists and deny lists, respectively. For example, [AllowedValues("apple", "banana", "mango")] . |
Cryptography
.NET 8 adds support for the SHA-3 hashing primitives. (SHA-3 is currently supported by Linux with OpenSSL 1.1.1 or later and Windows 11 Build 25324 or later.) APIs where SHA-2 is available now offer a SHA-3 compliment. This includes
SHA3_256
, SHA3_384
, and SHA3_512
for hashing; HMACSHA3_256
, HMACSHA3_384
, and HMACSHA3_512
for HMAC. The following example shows how to use the APIs, including the SHA3_256.IsSupported
property to determine if the platform supports SHA-3.Garbage collection
.NET 8 adds a capability to adjust the memory limit on the fly. This is useful in cloud-service scenarios, where demand comes and goes. To be cost-effective, services should scale up and down on resource consumption as the demand fluctuates. When a service detects a decrease in demand, it can scale down resource consumption by reducing its memory limit. Previously, this would fail because the garbage collector (GC) was unaware of the change and might allocate more memory than the new limit. With this change, you can call the_RefreshMemoryLimit
API to update the GC with the new memory limit. For now, the _RefreshMemoryLimit API is private, so you'll need to call it through private reflection.The following code snippet sets the heap hard limit to 100 mebibytes (MiB):
Native AOT support
The option to publish as native AOT was first introduced in .NET 7. Publishing an app with native AOT creates a fully self-contained version of your app that doesn't need a runtime—everything is included in a single file. .NET 8 brings the following improvements to native AOT publishing:- Adds support for the x64 and Arm64 architectures on macOS.
- Reduces the sizes of native AOT apps on Linux by up to 50%.
Performance improvements
.NET 8 includes improvements to code generation and just-in time (JIT) compilation:- Arm64 performance improvements
- SIMD improvements
- Support for AVX-512 ISA extensions (see Vector512 and AVX-512)
- Cloud-native improvements
- JIT throughput improvements
- Loop and general optimizations
.NET SDK changes
dotnet workload clean
command
dotnet restore
security auditing
Starting in .NET 8, you can opt into security checks for known vulnerabilities when dependency packages are restored. This auditing produces a report of security vulnerabilities with the affected package name, the severity of the vulnerability, and a link to the advisory for more details. When you run
dotnet add
or dotnet restore
, warnings NU1901-NU1904 will appear for any vulnerabilities that are found. For more information, see Audit for security vulnerabilities.Container performance and compatibility
.NET 8 has improved performance for pushing containers to remote registries, especially Azure registries. Speedup comes from pushing layers in one operation and, for registries that don't support atomic uploads, a more reliable chunking mechanism.These improvements also mean that more registries are supported: Harbor, Artifactory, Quay.io, and Podman.
EF Core 8
EF7 already introduced Raw SQL queries for scalar types, however, in EF8, raw SQL queries can now return any mappable CLR type not included in the Entity Framework model. Queries executed this way support Entity Framework features such as parametrized constructors and mapping attributes. Notably, relationships between the un-mapped type and other types in the model are not supported, since the un-mapped model cannot have foreign keys defined.DateOnly/TimeOnly supported on SQL Server
The DateOnly and TimeOnly types were introduced in .NET 6 and have been supported for several database providers (e.g. SQLite, MySQL, and PostgreSQL) since their introduction. For SQL Server, the recent release of a Microsoft.Data.SqlClient package targeting .NET 6 has allowed ErikEJ to add support for these types at the ADO.NET level. This in turn paved the way for support in EF8 for DateOnly and TimeOnly as properties in entity types.Previously, when scaffolding a SQL Server database with date or time columns, EF would generate entity properties with types DateTime and TimeSpan. Starting with EF Core 8.0, date and time are scaffolded as DateOnly and TimeOnly. [Breaking Changes]
Lazy-loading for no-tracking queries
EF8 adds support for lazy-loading of navigations on entities that are not being tracked by the DbContext. This means a no-tracking query can be followed by lazy-loading of navigations on the entities returned by the no-tracking query. For example, consider a no-tracking query for blogs:C# 12
Improved Switch Expressions
Switch expressions were introduced in C# 8, allowing developers to express complex conditional logic concisely and readably. In C# 12 a new pattern-matching syntax is introduced for switch expressions, which makes writing expressive and concise code even more accessible.For example, the below switch expression determines whether an integer is positive, negative, or zero.
With C# 12, we can simplify this code even further as shown below:
Async Streams
You can iterate through asynchronous data sources with the new async streams feature of C# 12.Default lambda parameters
You can now define default values for parameters on lambda expressions. The syntax and rules are the same as adding default values for arguments to any method or local function.You can learn more about default parameters on lambda expressions in the article on lambda expressions.
ASP.NET Core 8.0
SignalR: New approach to set the server timeout and Keep-Alive interval
ServerTimeout (default: 30 seconds) and KeepAliveInterval (default: 15 seconds) can be set directly on HubConnectionBuilder.Prior approach for JavaScript clients:
HTTP/3 enabled by default in Kestrel
HTTP/3 is a new internet technology that was standardized in June 2022. HTTP/3 offers several advantages over older HTTP protocols, including:- Faster connection setup.
- No head-of-line blocking.
- Better transitions between networks.
Support for generic attributes
Attributes that previously required a Type parameter are now available in cleaner generic variants. This is made possible by support for generic attributes in C# 11. For example, the syntax for annotating the response type of an action can be modified as follows:
Manage Request Timeouts
Microsoft presents a new middleware for handling request timeouts. Now, you can easily set timeouts for specific endpoints, controllers, or on-the-fly per request.
First, add the request timeout services:
builder.Services.AddRequestTimeouts();
app.UseRequestTimeouts();
For specific endpoints, use WithRequestTimeout(timeout)
or add [RequestTimeout(timeout)]
to the controller or action.
Keep in mind, timeouts are cooperative. When they expire, HttpContext.RequestAborted
triggers, but requests won’t be forcibly stopped. Your app should keep an eye on the token and decide when to wrap up request processing
Conclusion
In conclusion, .NET 8 and ASP.NET 8 have introduced an array of exciting new features that enhance the development experience and pave the way for more efficient and powerful applications. With these enhancements, .NET 8 and ASP.NET 8 solidify their positions as top choices for developers, enabling them to build cutting-edge solutions across a variety of platforms and industries. As the .NET ecosystem continues to evolve, it is evident that these new features mark yet another step forward in delivering a more robust and enjoyable development experience.