.NET 8 Features - What's new in .NET 8?

.NET 8 Features - What's new in .NET 8?

24 Sep 2024
Advanced
3.91K Views
18 min read
Learn with an interactive course and practical hands-on labs

.NET Course

.Net 8 Features: An Overview

.NET 8 is a free, cross-platform, and open-source programming framework that enables the development of various web, mobile, and cloud computing applications. This powerful open-source development platform has been driving the software industry for years. With every release of a new version, the technocrats become empowered to build more powerful, efficient, and secure applications.

Since its inception, the .NET framework has announced seven releases, each with a new set of enhancements. Recently, the successor of .NET 7, .NET 8, was released. .NET 8 is not only a framework version but is much more than that. It redefines the way software applications are built and deployed, enabling developers to meet the evolving demands of modern computing. It offers enhanced performance, improved diagnostic and observability, expanded cross-platform support, advanced tooling and integration, long-term support (LTS), and much more.

In this .NET tutorial, we'll discuss Microsoft's latest improvements and additions to the .NET 8 version.

For a detailed understanding, do consider:

Upgrades and Enhancements in .NET 8

Upgrades and Enhancements in .NET 8

Let's explore everything one by one:

  1. Software Development Kit (SDK) Changes

  1. Terminal Build Output

The dotnet build command builds a project and its dependencies into a set of binaries. In .NET 8, this command offers a new option to produce a more modernized build output. This terminal logger output enhances the grouping of errors based on their respective projects, improves the distinction between different target frameworks in multi-targeted projects, and offers real-time updates on the build process.

  1. Simplified Output Paths

Now, you can streamline the output path and folder structure for build outputs. All the build outputs are consolidated into a unified location. This change facilitates better predictability and compatibility with various development tools and utilities.

Read More - Advanced .Net Interview Questions

  1. Dotnet Workload Clean Command

This is a new command to clean up any leftover workload packs that may accumulate over multiple .NET Software Development Kit (SDK) or Visual Studio updates.

  1. Dotnet Publish and Dotnet Pack Assets

In .NET 8, the default behavior of the dotnet publish and dotnet pack commands has been updated to generate Release assets instead of Debug assets. These commands could be used to build and package your code for different purposes.

The dotnet build command prepares your code for execution and places the output in the Debug folder. Whereas, the dotnet publish command prepares your code for production use and saves the output in the Release folder.

  1. Template Engine

Now, the template engine has been enhanced to provide a more secure experience as it has included security features from NuGet. These improvements are as follows:

  • Preventing downloading packages from insecure http:// feeds. Therefore, if a source URL does not use https, attempting to install the template package will fail.
  • For commands such as dotnet new, dotNET new install, and dotnet new update, the template engine now checks for known vulnerabilities in the template package.
  • The dotnet new command now provides information about the owner of the template package.
  • The dotnet search and dotnet uninstall commands indicate whether a template is installed from a package that is considered “trusted.” Trusted packages use a reserved prefix, indicating their reliability.

  1. Core .NET Libraries

  1. Time Abstraction

The new TimeProvider class and ITimer interface in .NET 8 enable mock time in test scenarios. It even provides functionalities to retrieve local and UTC, obtain timestamps for performance measurement, and create timers.

  1. UTF8 Improvements

The introduction of the IUtf8SpanFormattable interface in .NET 8 enables writing string-like representations of your data type to UTF8 destinations. It also supports formatting to UTF8 from various primitive data types and provides TryWrite methods for UTF8-based formatting.

Example

static bool FormatHexVersion(
    short major,
    short minor,
    short build,
    short revision,
    Span utf8Bytes,
    out int bytesWritten) =>
    Utf8.TryWrite(
        utf8Bytes,
        CultureInfo.InvariantCulture,
        $"{major:X4}.{minor:X4}.{build:X4}.{revision:X4}",
        out bytesWritten);  

The implementation recognizes IUtf8SpanFormattable on the format values and uses their implementations to write their UTF8 representations directly to the destination span.

  1. Methods for Working with Randomness

The System.Random and System.Security.Cryptography.RandomNumberGenerator data types in .NET introduce new methods for working with randomness. These include GetItems() for randomly choosing items from an input set and Shuffle() for reducing training bias in machine learning.

The following example shows how to use System.Random.GetItems() (on the instance provided by the Random.Shared property) to randomly insert 31 items into an array.

Example of System.Random.GetItems<T>()

private static ReadOnlySpan<button> s_allButtons = new[]
{
    Button.Red,
    Button.Green,
    Button.Blue,
    Button.Yellow,
};

// ...

Button[] thisRound = Random.Shared.GetItems(s_allButtons, 31);
// Rest of game goes here ... 
Example of Shuffle<T>()

YourType[] trainingData = LoadTrainingData();
Random.Shared.Shuffle(trainingData);

IDataView sourceData = mlContext.Data.LoadFromEnumerable(trainingData);

DataOperationsCatalog.TrainTestData split = mlContext.Data.TrainTestSplit(sourceData);
model = chain.Fit(split.TrainSet);

IDataView predictions = model.Transform(split.TestSet);
// ...    

  1. Performance-Focused Data Types

The new System.Collections.Frozen namespace in .NET 8 introduces FrozenDictionary and FrozenSet data types that allow read-only collections for faster read operations. Additionally, System.Buffers.IndexOfAnyValues optimizes searching for the first occurrence of any value in a collection.


private static readonly FrozenDictionary<string, bool> s_configurationData =
    LoadConfigurationData().ToFrozenDictionary(optimizeForReads: true);

// ...
if (s_configurationData.TryGetValue(key, out bool setting) && setting)
{
    Process();
}

  1. System.Numerics and System.Runtime.Intrinsics

Vector256, Matrix3x2, and Matrix4x4 have improved the hardware acceleration on .NET 8. The hardware intrinsics in .NET 8 are annotated with the ConstExpected attribute, ensuring you get information on when the underlying hardware expects a constant or a non-constant. Also, the added Lerp(TSelf, TSelf, TSelf) API provides linear interpolation between the two values to be performed efficiently and accurately.

  1. Data Validation

The System.ComponentModel.DataAnnotations namespace in .NET 8 includes new attributes for data validation in cloud-native services. These are specifically designed to validate non-user-entry data, such as configuration options.

  1. Extension of .NET Libraries

  1. ValidateOptionsResultBuilder Type

It simplifies the creation of ValidateOptionsResult objects, allowing for the accumulation of multiple errors during validation. This is particularly useful when implementing the IValidateOptions.Validate method because it enables better handling of validation errors.

Example of ValidateOptionsResultBuilder

ValidateOptionsResultBuilder builder = new();
builder.AddError("Error: invalid operation code");
builder.AddResult(ValidateOptionsResult.Fail("Invalid request parameters"));
builder.AddError("Malformed link", "Url");

// Build ValidateOptionsResult object has accumulating multiple errors.
ValidateOptionsResult result = builder.Build();

// Reset the builder to allow using it in new validation operation.
builder.Clear();

  1. Garbage Collection Memory Limit Adjustment

Now one can dynamically adjust the memory limit for garbage collection. Also, the _RefreshMemoryLimit API allows updating the garbage collector with the new memory limit, ensuring efficient resource utilization.

  1. Source Generator for Configuration Binding

ASP.NET Core uses configuration providers to read key-value pair data from various sources for app configuration. With the source generator in .NET 8, you can opt-in to generate binding implementations for configuration mapping. This eliminates the reliance on reflection – which causes issues with trimming and Native AOT – and improves performance and compatibility.


using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;

WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
IConfigurationSection section = builder.Configuration.GetSection("MyOptions");

// !! Configure call - to be replaced with source-gen'd implementation
builder.Services.Configure(section);

// !! Get call - to be replaced with source-gen'd implementation
MyOptions options0 = section.Get();

// !! Bind call - to be replaced with source-gen'd implementation
MyOptions options1 = new MyOptions();
section.Bind(options1);

WebApplication app = builder.Build();
app.MapGet("/", () => "Hello World!");
app.Run();

public class MyOptions
{
    public int A { get; set; }
    public string S { get; set; }
    public byte[] Data { get; set; }
    public Dictionary Values { get; set; }
    public List Values2 { get; set; }
}

public class MyClass
{
    public int SomethingElse { get; set; }
}

  1. Reflection Improvements

You might have observed that in the previous versions of .NET, an IntPtr was returned instead of a System.Type object while working with function pointers and using reflection operations like typeof or FieldInfo.FieldType. This limited the ability to access the metadata of function pointers, such as calling conventions, return types, and parameters.

However, in .NET 8, improvements have been made to reflection to support function pointers. Now, when using typeof or working with FieldInfo.FieldType on a function pointer, a System.Type object is returned. This enables you to access and utilize the metadata associated with function pointers, allowing for more comprehensive reflection operations on these data types.

Example of some of the new APIs for Reflection Improvements

// Sample class that contains a function pointer field.
public unsafe class UClass
{
    public delegate* unmanaged[Cdecl, SuppressGCTransition] _fp;
}

// ...

FieldInfo fieldInfo = typeof(UClass).GetField(nameof(UClass._fp));

// Obtain the function pointer type from a field.
Type fpType = fieldInfo.FieldType;

// New methods to determine if a type is a function pointer.
Console.WriteLine(
    $"IsFunctionPointer: {fpType.IsFunctionPointer}");
Console.WriteLine(
    $"IsUnmanagedFunctionPointer: {fpType.IsUnmanagedFunctionPointer}");

// New methods to obtain the return and parameter types.
Console.WriteLine($"Return type: {fpType.GetFunctionPointerReturnType()}");

foreach (Type parameterType in fpType.GetFunctionPointerParameterTypes())
{
    Console.WriteLine($"Parameter type: {parameterType}");
}

// Access to custom modifiers and calling conventions requires a "modified type".
Type modifiedType = fieldInfo.GetModifiedFieldType();

// A modified type forwards most members to its underlying type.
Type normalType = modifiedType.UnderlyingSystemType;

// New method to obtain the calling conventions.
foreach (Type callConv in modifiedType.GetFunctionPointerCallingConventions())
{
    Console.WriteLine($"Calling convention: {callConv}");
}

// New method to obtain the custom modifiers.
var modifiers =
    modifiedType.GetFunctionPointerParameterTypes()[0].GetRequiredCustomModifiers();

foreach (Type modreq in modifiers)
{
    Console.WriteLine($"Required modifier for first parameter: {modreq}");
}
Output
IsFunctionPointer: True
IsUnmanagedFunctionPointer: True
Return type: System.Void
Parameter type: System.Int32&
Calling convention: System.Runtime.CompilerServices.CallConvSuppressGCTransition
Calling convention: System.Runtime.CompilerServices.CallConvCdecl
Required modifier for first parameter: System.Runtime.InteropServices.InAttribute

  1. Native Ahead-of-Time (AOT) Compilation

Unlike traditional just-in-time (JIT) compilation, where code is compiled to machine code at runtime, Native AOT compiles managed code directly into native machine code during the build process. Native AOT enables the creation of a self-contained version of the app that does not require a separate runtime, bundling everything into a single file.

To understand the significance of Native AOT, let’s get into its major aspects:

  • Improved Startup Time: In traditional JIT compilation, the first execution of a method incurs a compilation delay, impacting application startup times. However, with Native AOT, the compilation process occurs during the build phase. Consequently, .NET 8 applications experience minimal warm-up times and respond instantaneously to user interactions.
  • Reduced Memory Footprint: By compiling directly to native code, Native AOT reduces the memory footprint of .NET applications.

  1. Performance Improvements

  • Arm64 performance enhancements
  • Single Instruction, Multiple Data (SIMD) improvements
  • Support for AVX-512 (Advanced Vector Extensions) ISA extensions
  • Cloud-native improvements
  • Profile-Guided Optimization (PGO) improvements
  • Just-in-Time (JIT) throughput improvements
  • Loop and general optimizations
  • Optimized access for fields marked with ThreadStaticAttribute
  • Consecutive register allocation
  • JIT/NativeAOT memory operations

  1. Security Enhancements

  1. Secure Software Supply Chain Capabilities

.NET 8 addresses security vulnerabilities by enabling cryptographic signing of assemblies, allowing developers to verify the authenticity and integrity of dependencies before they are integrated into the application.

Moreover, .NET 8 emphasizes secure source control practices, facilitating the use of signed Git commits and ensuring that the source code remains secure throughout its development lifecycle. By enforcing secure source control practices, .NET 8 minimizes the risk of unauthorized changes and malicious code injections, reinforcing the integrity of the application’s source code.

  1. Improvements to Auth and Identity in ASP.NET Core

New APIs will make authentication, authorization, and identity management (collectively referred to as “auth”) easier to customize the user login and identity management experience. New endpoints will enable token-based authentication and authorization in Single Page Applications (SPA) with no external dependencies.

  1. Code Generation Enhancements

The .NET 8 release introduced some significant code generation enhancements that can contribute to faster and more efficient execution of .NET applications.

  1. Advanced Memory Management

By reducing memory fragmentation and improving memory locality, applications can better leverage system resources, resulting in smoother performance and reduced memory-related bottlenecks.

  1. Enhanced Optimization Techniques

In .NET 8 the compiler intelligently analyzes the code, identifies opportunities for optimizations, and generates highly efficient machine code. These optimizations range from loop unrolling and constant folding to inlining and dead code elimination, resulting in faster and more streamlined execution paths.

  1. Hardware-Specific Instructions

By generating code that utilizes specialized instructions available on modern CPUs, such as SIMD (Single Instruction, Multiple Data) instructions, .NET 8 significantly boosts the performance of applications that perform vectorized computations and data parallelism.

  1. Serialization Improvements

In .NET 8, several improvements have been made to the serialization and deserialization functionality of System.Text.Json. These are as follows:

  • Performance and reliability enhancements for the source generator in native AOT apps.
  • Support for serializing types with required and init properties.
  • Customization of handling members that are not present in the JSON payload.
  • Explicit control over frozen JsonSerializerOptions instances.
  • Replacement of deprecated AddContext() method with TypeInfoResolver and TypeInfoResolverChain properties.
  • Support for compiler-generated or unspeakable types in weakly typed source generation scenarios, allowing System.Text.Json to dynamically determine the appropriate supertype for serialization at runtime.

Read More:

Summary

In this blog post, we have seen some of the important updates in .NET 8. These improvements will make the development smooth for the developers. Microsoft’s .NET 8 release is a major leap forward in building scalable, secure, robust, and performant applications. With the release of .NET 8, C# 12 was also made available. To get into more details, enroll in our .NET Training Program.

FAQs

The primary distinction between.NET 7 and.NET 8 is in their features, improvements, and long-term support (LTS) status. .NET 7 is a current release rather than an LTS version, hence its support is limited compared to.NET 8, which is a long-term support release. 

  • Performance Improvements:.NET 8 expands on the performance improvements offered in.NET 7, making programs faster, particularly in cases involving serialization, regular expressions, and web development. 
  • Native AOT (Ahead-of-Time) Improvements:.NET 8 builds on the foundation of AOT, which was introduced in.NET 7. AOT converts apps into native code, resulting in faster startup times and lower memory utilization. 
  • Container Optimization: Both.NET 7 and.NET 8 focus extensively on containerized apps, but.NET 8 further extends these optimizations to improve performance.

.NET 6 (LTS):

  • Long-Term Support (LTS): .NET 6 is a stable release with long-term support, making it a go-to version for production applications that require extended maintenance.
  • Cross-platform Development: Supports building applications for Linux, macOS, and Windows.
  • C# 10: Introduced new language features such as global using directives, record struct, and more.
  • Minimal APIs: Introduced minimal APIs for simpler and more efficient microservices development.
  • Hot Reload: Improved developer productivity with the Hot Reload feature, enabling you to apply code changes without restarting the application
 .NET 8 (LTS): 
  • Native AOT (Ahead-of-Time) Compilation: Further enhances AOT support for faster startup and reduced memory consumption.
  • Performance Gains: Significant improvements in serialization, garbage collection, and regex matching, especially for cloud and web applications.
  • Blazor Hybrid Apps: Extends the functionality of Blazor to build hybrid apps that can run on multiple platforms.
  • Improved Containerization: Smaller and more efficient container images for cloud-native development.
  • C# 12 Features: Introduces more advanced C# language features such as default type inference and better pattern matching.

This namespace in .NET 8 introduces FrozenDictionary and FrozenSet data types that allow read-only collections for faster read operations.

NET 8 addresses security vulnerabilities by enabling cryptographic signing of assemblies, allowing developers to verify the authenticity and integrity of dependencies before they are integrated into the application.


Upgrading to .NET 8 is worth considering due to its performance improvements, new features like Native AOT (Ahead of Time) compilation, and enhanced support for cloud-native applications. It also brings updates in C# 12, better developer productivity, and extended platform support, making it a strong choice for modernizing applications and staying current with the latest technology 

.NET 8 introduces several improvements to the garbage collector (GC), focusing on performance and efficiency. It includes better memory utilization and reduced latency by optimizing Gen2 object collections, leading to faster application responsiveness. Additionally, improvements in multi-threaded workloads and concurrent GC help minimize pauses during garbage collection, further enhancing scalability in large applications.
Share Article
About Author
Shailendra Chauhan (Microsoft MVP, Founder & CEO at Scholarhat by DotNetTricks)

Shailendra Chauhan is the Founder and CEO at ScholarHat by DotNetTricks which is a brand when it comes to e-Learning. He provides training and consultation over an array of technologies like Cloud, .NET, Angular, React, Node, Microservices, Containers and Mobile Apps development. He has been awarded Microsoft MVP 9th time in a row (2016-2024). He has changed many lives with his writings and unique training programs. He has a number of most sought-after books to his name which has helped job aspirants in cracking tough interviews with ease.
Accept cookies & close this