What’s New in .NET 8 🧐 ? Discover ALL .NET 8 Features⚡🚀
In this post, I'll briefly mention the new features of .NET 8 and the changes.
dotnet publish
and dotnet pack
Release Mode 🏭
With this new version, dotnet publish
and dotnet pack
commands will build and pack with the Release
mode. Before it was producing in Debug
mode. To be able to produce in Debug mode, you need to set this parameter -p:PublishRelease
as false.
dotnet publish -> /app/bin/Release/net8.0/app.dll
dotnet publish -p:PublishRelease=false -> /app/bin/Debug/net8.0/app.dll
System.Text.Json Serialization 🧱
System.Text.Json replaced Newtonsoft.Json in the recent versions. We are also using System.Text.Json
in the ABP Framework now. There are several enhancements to object serialization and deserialization.
The latest version of the source generator now offers improved performance and reliability for Native AOT apps when used with ASP.NET Core. It also allows serializing types with required
and init
properties already supported in reflection-based serialization. Additionally, there is now an option to customize the handling of members that are not present in the JSON payload, see https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/missing-members. Support for serializing properties from interface hierarchies. The JsonNamingPolicy feature has been expanded to include new naming policies for snake_case
and kebab-case
property name conversions. Finally, JsonSerializerOptions.MakeReadOnly method allows for explicit control over when a JsonSerializerOptions
instance is frozen, and you can check its status using the IsReadOnly property.
Randomness
AI programming is very popular these days. And the need to produce more random content arose.
GetItems() 🧮
Two new methods: Random.GetItems and RandomNumberGenerator.GetItems have been introduced that enable developers to randomly select a set number of items from a given input set. The example below demonstrates the usage of the System.Random.GetItems<T>()
method using an instance obtained from the Random.Shared
property to randomly insert 31 items into an array.
private static ReadOnlySpan<CountryPhoneCodePhoneCode> countries = new[]
{
new CountryPhoneCode("Turkey", "90"),
new CountryPhoneCode("China", "86"),
new CountryPhoneCode("Germany", "49"),
new CountryPhoneCode("Finland", "358"),
new CountryPhoneCode("Spain", "34")
};
var randomValues = Random.Shared.GetItems(countries, 2);
foreach (var x in randomValues)
{
Console.WriteLine(x.Name + " -> " + x.CountryPhoneCode);
}
/**************
- Output -
Germany -> 49
Finland -> 358
**************/
Shuffle() 🔀
If you need to randomize the order of a span in your application, you can take advantage of two new methods: Random.Shuffle and RandomNumberGenerator.Shuffle. These methods are particularly handy when you want to minimize the impact of training bias in machine learning by varying the order in which training and testing data are presented. Using these methods, you can ensure that the first thing in your dataset is only sometimes used for training, and the last is only sometimes reserved for testing.
var trainingData = GetData();
Random.Shared.Shuffle(trainingData);
IDataView source = mlContext.Data.LoadFromEnumerable(trainingData);
DataOperationsCatalog.TrainTestData splittedData = mlContext.Data.TrainTestSplit(source);
model = chain.Fit(splittedData.TrainSet);
IDataView resultPredictions = model.Transform(split.TestSet);
Performance Improvements 🚀
In .NET 8, various new types have been introduced to enhance application performance.
The System.Collections.Frozen namespace in .NET 8 includes the FrozenDictionary and FrozenSet collection types. These types are designed to prevent changes to keys and values once a collection is created, resulting in faster read operations such as
TryGetValue()
. They are particularly useful for collections populated on first use and then persisted for a long-lived service.private static readonly FrozenDictionary<string, bool> frozenData = LoadConfigurationData().ToFrozenDictionary(optimizeForReads: true); ////// if (frozenData.TryGetValue(key, out bool setting) && setting) { Process(); }
Buffers.IndexOfAnyValues is a new type in .NET 8, designed to be passed to methods that search for the first occurrence of any value in a passed collection. The new overloads of methods like String.IndexOfAny and MemoryExtensions.IndexOfAny accept an instance of the new type. When you create an instance of Buffers.IndexOfAnyValues, all the necessary data for optimizing subsequent searches is derived at that time.
Text.CompositeFormat is a new type in .NET 8 useful for optimizing format strings that aren't known at compile time (such as format strings loaded from a resource file). While some extra time is spent upfront to perform tasks like parsing the string, it saves the work from being done each time the format string is used.
private static readonly CompositeFormat range = CompositeFormat.Parse(Load()); ////////// static string GetMessage(int min, int max) => string.Format(CultureInfo.InvariantCulture, range, min, max);
In .NET 8, two new types are introduced to implement the fast XxHash3 and XxHash128 hash algorithms.
Improvements in System.Numerics and System.Runtime.Intrinsics 🔥
There are several enhancements made to the System.Numerics and System.Runtime.Intrinsics namespaces. These improvements include better hardware acceleration for Vector256, Matrix3x2, and Matrix4x4 in .NET 8.
Vector256 was redesigned to utilize 2x Vector128<T>
operations internally to achieve partial acceleration of certain functions on Arm64
processors where Vector128.IsHardwareAccelerated == true
but Vector256.IsHardwareAccelerated == false
. The introduction of Vector512 is also included in .NET 8.
Additionally, the ConstExpected
attribute has been added to hardware intrinsic to alert users when a non-constant value might cause unexpected performance issues.
Lastly, the Lerp(TSelf, TSelf, TSelf) API has been added to IFloatingPointIeee754, enabling the efficient and accurate linear interpolation of two values in float
(Single), double
(Double), and Half.
New Data Validation Attributes 🛡️
The DataAnnotations namespace, aimed specifically for validation in cloud-native services. The existing DataAnnotations
validators are primarily used for validating user data, like form fields. However, the new attributes are meant to validate data, not entered by users, like configuration options. Apart from the new attributes, the RangeAttribute and RequiredAttribute types also received new properties.
- RequiredAttribute.DisallowAllDefaultValues: The attribute forces that structs for inequality with their default values.
- RangeAttribute.MinimumIsExclusive & RangeAttribute.MaximumIsExclusive: Specifies whether the allowable range includes its boundaries or not.
- DataAnnotations.LengthAttribute: Specifies the lower and upper limits for strings or collections using the
Length
attribute. For instance, the[Length(5, 100)]
attribute specifies that a collection must have at least 5 elements and at most 100 elements. - DataAnnotations.Base64StringAttribute: Validates a valid
Base64
format. - DataAnnotations.AllowedValuesAttribute & DataAnnotations.DeniedValuesAttribute: Specifies accepted allow lists or not allowed deny lists. For instance:
[AllowedValues("red", "green", "blue")]
or[DeniedValues("yellow", "purple")]
.
Function Pointers Introspection Support ↩️
Function pointers were released with .NET 5. There was no support for reflection at that time. As a result, using typeof
or reflection on a function pointer, such as typeof(delegate*<void>())
or FieldInfo.FieldType
, respectively, would return an IntPtr. However, in .NET 8, a System.Type object is returned instead, providing access to function pointer metadata, such as calling conventions, return type, and parameters. This functionality is implemented only in the CoreCLR
runtime and MetadataLoadContext.
Native AOT 🏭
The publishing as native AOT was initially introduced in .NET 7, the option to publish an application as 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.
In .NET 8, the support for native AOT now encompasses the x64
and Arm64
architectures on macOS. Moreover, native AOT applications on Linux are now up to 50% smaller in size. Here's the table, illustrates the size of a minimal app published with native AOT, containing the entire .NET runtime:
- Linux x64 (with
-p:StripSymbols=true
)- .NET 7 ➡ 3.76MB
- .NET 8 ➡ 1.84 MB
- Windows x64
- .NET 7 ➡ 2.85 MB
- .NET 8 ➡ 1.77 MB
Code Generation Improvements 📃
.NET 8 includes enhancements to code generation and just-in-time (JIT) compilation:
- JIT throughput improvements
- Arm64 performance improvements
- Profile-guided optimization (PGO) improvements
- Support for AVX-512 ISA extensions
- SIMD improvements
- Cloud-native improvements
- Loop and general optimizations
.NET 8 DevOps Improvements 📦
NET Container Image Changes
There are some changes with .NET 8 on image containers. First, Debian 12 is the default Linux distribution in the container images.
Secondly, the images include a non-root
user to make the images non-root
capable. To run as non-root
, add the line USER app
at the end of your Dockerfile
.
Besides, the default port has also changed from 80
to 8080
and a new environment variable ASPNETCORE_HTTP_PORTS
is available to change ports easily.
Also, the format for the ASPNETCORE_HTTP_PORTS
variable is easier compared to the format required by ASPNETCORE_URLS
, and it accepts a list of ports. If you change the port back to 80
using one of these variables, it won’t be possible to run as non-root
.
Finally, .NET 8 is now supported on Chiseled Ubuntu images, available at the [Ubuntu/DotNet-deps Docker Hub](Ubuntu/DotNet-deps Docker Hub). Chiseled images are designed to have a smaller attack surface as they are stripped down to be ultra-compact, and do not include a package manager or shell. Chiseled images are non-root, making them ideal for developers looking for the benefits of appliance-style computing. These images are regularly published to the .NET nightly artifact registry for easy access.
Building Your .NET on Linux
Previously, building .NET from source in earlier versions required creating a source tarball
from the corresponding release commit in the [dotnet/installer repository](dotnet/installer repository). However, in .NET 8, this step is no longer necessary as the dotnet/dotnet repository allows building .NET directly on Linux using dotnet/source-build to create runtimes, tools, and SDKs. Red Hat and Canonical also use this build for .NET. Building in a container is the easiest approach for most people since the dotnet-buildtools/prereqs
container images have all the necessary dependencies. The build instructions provide more information.
Minimum support baselines for Linux
The support requirements for Linux have been updated for .NET 8, with changes to the minimum support baselines:
- All architectures will target Ubuntu 16.04 for building .NET, which is important for setting the minimum required version of
glibc
for .NET 8. Versions of Ubuntu earlier than 16.04, such as 14.04, will not even allow .NET 8 to start. - Red Hat Enterprise Linux 7 is no longer supported with .NET 8. Only supporting RHEL 8 and later.
For further details, please refer to the support for Red Hat Enterprise Linux Family page.
Become a pioneer and try the new features of .NET 8 now.
Adapt it to your project or start a new .NET 8 project.
Claim your copy of .NET 8 today 🏎️ !
〰️〰️〰️
Happy Coding ⌨️
I'm Alper Ebicoglu 🧑🏽💻 ABP Framework Core Team Member
Follow me for the latest news about .NET and software development:
📌 twitter.com/alperebicoglu
📌 github.com/ebicoglu
📌 linkedin.com/in/ebicoglu
📌 medium.com/@alperonline
Comments
Enis Necipoğlu 86 weeks ago
Awesome!
Tarık Özdemir 86 weeks ago
Great to know
Berkan Şaşmaz 86 weeks ago
Great article!
Halil İbrahim Kalkan 86 weeks ago
Thanks. Great post.
Masum ULU 86 weeks ago
Great article. Thanks.
Kirti Kulkarni 86 weeks ago
Good to know. Thanks
Engincan Veske 85 weeks ago
Great article, thanks for sharing.
Pase Stars 83 weeks ago
Great post. Thanks
Qais Al khateeb 58 weeks ago
When can we upgrade to ABP v8?
Alper Ebiçoğlu 58 weeks ago
.NET8 will come with ABP v8.0 we have already upgraded the framework to .NET8-rc.2 and our websites are running on .NET8 (you can see the footer)
Alper Ebiçoğlu 58 weeks ago
.NET8 will come with ABP v8.0 we have already upgraded the framework to .NET8-rc.2 and our websites are running on .NET8 (you can see the footer)
Enis Necipoğlu 57 weeks ago
Thanks! Great Article