What's new in .NET 8? Discover ALL .NET 8 Features

What's new in .NET 8? Discover ALL .NET 8 Features

02 Jan 2024
14 min read
Learn via Video Course & by Doing Hands-on Labs

.NET Course

.NET 8: 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 has been released. .NET 8 is not only a framework version but 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 ASP.NET tutorial, we'll discuss the latest improvements and additions made in the .NET 8 version by Microsoft.

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.

  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.


static bool FormatHexVersion(
    short major,
    short minor,
    short build,
    short revision,
    Span utf8Bytes,
    out int bytesWritten) =>
        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[] thisRound = Random.Shared.GetItems(s_allButtons, 31);
// Rest of game goes here ... 
Example of Shuffle<T>()

YourType[] trainingData = LoadTrainingData();

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)

  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.

  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

// !! 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();

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

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.
    $"IsFunctionPointer: {fpType.IsFunctionPointer}");
    $"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 =

foreach (Type modreq in modifiers)
    Console.WriteLine($"Required modifier for first parameter: {modreq}");
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, secure source control practices are emphasized in .NET 8, 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.

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 ASP.NET Training Program.


Q1. What is Native Ahead-of-Time (AOT) Compilation?

Native AOT compiles managed code directly into native machine code during the build process.

Q2. What are the UTF8 Improvements in .NET 8?

The introduction of the IUtf8SpanFormattable interface in .NET 8 enables writing string-like representations of your data type to UTF8 destinations.

Q3. What's the benefit of System.Collections.Frozen namespace in .NET 8?

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

Q4. What about the security updates in .NET 8?

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.

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 8th time in a row (2016-2023). 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