.NET 8 succeeds .NET 7 and is designated as a long-term support (LTS) release, ensuring support for three years. In this blog, we go through the new features in the .NET SDK and tooling for .NET 8.
SDK
We will go through the following sub topics –
- CLI-based project evaluation
- Terminal build output
- Simplified output paths
- `dotnet workload clean’` command
- ‘dotnet publish’ and ‘dotnet pack’ assets
- Template engine
- Source Link
- Source-build SDK
CLI-based project evaluation
MSBuild now offers a feature that simplifies integrating MSBuild data into your scripts or tools. The following new flags can be used with CLI commands like `dotnet publish` to extract data for use in CI pipelines and other applications.
|
Flag |
Description |
|
–getProperty:<PROPERTYNAME> |
Retrieves the MSBuild property with the specified name. |
|
–getItem:<ITEMTYPE> |
Retrieves MSBuild items of the specified type. |
|
–getTargetResults:<TARGETNAME> |
Retrieves the outputs from running the specified target. |
Values are written to the standard output. For multiple or complex values, the output is formatted as JSON, as demonstrated in the following examples.
>dotnet publish --getProperty:OutputPath
bin\Release\net8.0\
>dotnet publish -p PublishProfile=DefaultContainer --getProperty:GeneratedContainerDigest --getProperty:GeneratedContainerConfiguration
{
"Properties": {
"GeneratedContainerDigest": "sha256:ef880a503bbabcb84bbb6a1aa9b41b36dc1ba08352e7cd91c0993646675174c4",
"GeneratedContainerConfiguration": "{\u0022config\u0022:{\u0022ExposedPorts\u0022:{\u00228080/tcp\u0022:{}},\u0022Labels\u0022...}}"
}
}
>dotnet publish -p PublishProfile=DefaultContainer --getItem:ContainerImageTags
{
"Items": {
"ContainerImageTags": [
{
"Identity": "latest",
...
]
}
}
Terminal build output
The `dotnet build` command now includes an option to produce more modernized build output. This updated terminal logger output groups errors with their respective projects, better differentiates target frameworks for multi-targeted projects, and provides real-time information about the build process. To enable this new output, use the `–tl` option.
Simplified output paths
.NET 8 introduces a feature that simplifies the output path and folder structure for build outputs. Previously, .NET applications generated a complex and deeply nested set of output paths for different build artifacts. The new simplified output path structure consolidates all build outputs into a common location, making it easier for tools to predict and manage these outputs.
‘dotnet workload clean’ command
.NET 8 introduces a new command to clean up workload packs that might be left over from multiple .NET SDK or Visual Studio updates. If you encounter issues when managing workloads, consider using the workload clean command to safely restore to a known state before trying again. The command has two modes:
-
-
dotnet workload clean
-
In .NET 8, the `workload clean` command conducts workload garbage collection for both file-based and MSI-based workloads. This process targets orphaned packs, which are leftover from uninstalled versions of the .NET SDK or packs lacking installation records.
Additionally, if Visual Studio is installed, the command provides a list of workloads that require manual cleanup using Visual Studio.
-
-
dotnet workload clean --all
-
This mode takes a more assertive approach by removing every pack on the machine that corresponds to the current SDK workload installation type (excluding those originating from Visual Studio). Additionally, it clears all workload installation records for the current .NET SDK feature band and any previous versions.
‘dotnet publish’ and ‘dotnet pack’ assets
As the dotnet publish and dotnet pack commands are geared towards generating production assets, they now default to producing Release assets.
The following output illustrates the contrast in behavior between dotnet build and dotnet publish and provides guidance on reverting to publishing Debug assets by setting the PublishRelease property to false.
/app# dotnet new console /app# dotnet build app -> /app/bin/Debug/net8.0/app.dll /app# dotnet publish app -> /app/bin/Release/net8.0/app.dll app -> /app/bin/Release/net8.0/publish/ /app# dotnet publish -p:PublishRelease=false app -> /app/bin/Debug/net8.0/app.dll app -> /app/bin/Debug/net8.0/publish/
Template engine
- The template engine provides a more secure experience in .NET 8 by integrating some of NuGet’s security-related features. The improvements include:
-
By default, downloading packages from HTTP feeds is now prevented. For instance, attempting to install the template package using the following command will fail because the source URL doesn’t utilize HTTPS:
dotnet new install console --add-source "http://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public/nuget/v3/index.json"To override this limitation, you can use the
--forceflag. -
Additionally, for commands such as
dotnet new,dotnet new install, anddotnet new update, known vulnerabilities in the template package are checked. If vulnerabilities are detected and you wish to proceed, you must use the--forceflag. -
For
dotnet new, information about the template package owner is provided. Ownership is verified by the NuGet portal and can be considered a trustworthy characteristic. -
Moreover, for commands like
dotnet searchanddotnet uninstall, it is indicated whether a template is installed from a package that is “trusted”—meaning it utilizes a reserved prefix.
Source Link
Source Link has been incorporated into the .NET SDK. This integration means that Source Link is included as part of the SDK itself, eliminating the need for a separate <PackageReference> for the package. The objective is to encourage more packages to include Source Link information by default, thereby enhancing the developer experience in IDEs.
Source-build SDK
The Linux distribution-built (source-build) SDK now possesses the ability to construct self-contained applications utilizing the source-build runtime packages. These distribution-specific runtime packages are packaged alongside the source-build SDK. In self-contained deployment scenarios, the bundled runtime package is referenced, facilitating this functionality for users.
Native AOT console app template
The default console app template now features built-in support for AOT (Ahead of Time) compilation. To create a project configured for AOT compilation, simply execute the command dotnet new console --aot. The project configuration introduced by --aot delivers three key benefits:
-
Generates a native self-contained executable with Native AOT during project publishing, such as with
dotnet publishor Visual Studio. -
Enables compatibility analyzers for trimming, AOT, and single file, which identify potentially problematic areas within your project.
-
Enables debug-time emulation of AOT, ensuring a similar debugging experience even without AOT compilation. For instance, if you utilize System.Reflection.Emit in a NuGet package lacking AOT annotation, the emulation ensures no surprises during project publishing with AOT.
.NET on Linux
Minimum support baselines for Linux
The Linux support baseline for .NET 8 has been updated, targeting Ubuntu 16.04 across all architectures. This adjustment is crucial for establishing the minimum required glibc version. As a result, .NET 8 will not start on distribution versions with an older glibc, such as Ubuntu 14.04 or Red Hat Enterprise Linux 7.
Build your own .NET on Linux
In previous versions of .NET, building from source required creating a “source tarball” from the dotnet/installer repository commit corresponding to a release. However, in .NET 8, this step is no longer necessary. You can now directly build .NET on Linux from the dotnet/dotnet repository. This repository utilizes dotnet/source-build to build .NET runtimes, tools, and SDKs, which is the same build process used by Red Hat and Canonical.
For most users, building in a container is the simplest approach, as the dotnet-buildtools/prereqs container images contain all the necessary dependencies.
NuGet signature verification
Beginning with .NET 8, NuGet now verifies signed packages on Linux by default, while continuing to do so on Windows as well.
For most users, this verification process should go unnoticed. However, if you encounter trust failures along with warning NU3042 and have an existing root certificate bundle located at /etc/pki/ca-trust/extracted/pem/objsign-ca-bundle.pem, you may be affected.
To opt out of this verification process, you can set the environment variable DOTNET_NUGET_SIGNATURE_VERIFICATION to false.
Code analysis
.NET 8 includes several new code analyzers and fixers to help verify that you’re using .NET library APIs correctly and efficiently. The following table summarizes the new analyzers.
|
Rule ID |
Category |
Description |
|
CA1856 |
Performance |
Fires when the ConstantExpectedAttribute attribute is not applied correctly on a parameter. |
|
CA1857 |
Performance |
Fires when a parameter is annotated with ConstantExpectedAttribute but the provided argument isn’t a constant. |
|
CA1858 |
Performance |
To determine whether a string starts with a given prefix, it’s better to call String.StartsWith than to call String.IndexOf and then compare the result with zero. |
|
CA1859 |
Performance |
This rule recommends upgrading the type of specific local variables, fields, properties, method parameters, and method return types from interface or abstract types to concrete types when possible. Using concrete types leads to higher quality generated code. |
|
CA1860 |
Performance |
To determine whether a collection type has any elements, it’s better to use Length, Count, or IsEmpty than to call Enumerable.Any. |
|
CA1861 |
Performance |
Constant arrays passed as arguments aren’t reused when called repeatedly, which implies a new array is created each time. To improve performance, consider extracting the array to a static readonly field. |
|
CA1865-CA1867 |
Performance |
The char overload is a better-performing overload for a string with a single char. |
|
CA2021 |
Reliability |
Enumerable.Cast<TResult>(IEnumerable) and Enumerable.OfType<TResult>(IEnumerable) require compatible types to function correctly. Widening and user-defined conversions aren’t supported with generic types. |
|
CA1510-CA1513 |
Maintainability |
Throw helpers are simpler and more efficient than an if block constructing a new exception instance. These four analyzers were created for the following exceptions: ArgumentNullException, ArgumentException, ArgumentOutOfRangeException and ObjectDisposedException. |
Diagnostics
C# Hot Reload supports modifying generics
In .NET 8, C# Hot Reload now includes support for modifying generic types and generic methods. This means that when you debug console, desktop, mobile, or WebAssembly applications using Visual Studio, you can make changes to generic classes and generic methods in C# code or Razor pages.