.NET 8 Top 10 New Features - NDepend Blog (2024)

In .NET 8, System.Text.Json brings an array of thrilling updates for developers. This release elevates the user experience in Native AOT (Ahead-Of-Time) applications thanks to many improvements on the source generator including:

  1. Supports serializing types with requiredand init properties.
  2. JsonSourceGenerationOptionsAttribute: Aligns with JsonSerializerOptions, enabling compile-time serialization configuration.
  3. Improved Type Handling: Ignores inaccessible properties, allows nesting JsonSerializerContext declarations, and handles compiler-generated types dynamically.
  4. JsonStringEnumConverter<TEnum>: A new converter type simplifies enum serialization in Native AOT applications.
  5. Additionally, the JsonConverter.Type property helps retrieve the type of a non-generic JsonConverter instance, with nullable support for various scenarios.

Many other enhancements are packed including:

  • JsonNamingPolicy now incorporates new naming policies for converting property names tosnake_case (with underscores) and kebab-case(with hyphens).
  • You can now deserialize data onto read-only fields or read-only properties, which are those without a set accessor.
  • You can now opt to disable the reflection-based serializer as the default option. This capability is valuable for preventing the unintended inclusion of reflection components, particularly in trimmed and Native AOT applications.

More information about System.Text.Json improvements can be found in this official post: What’s new in System.Text.Json in .NET 8

Convenient New APIs for Managing Randomness

.NET 8 unveils game-changing methods to improve our approach to randomness. This is especially useful for machine learning applications. For example the new methods System.Random.GetItems()andSystem.Security.Cryptography.RandomNumberGenerator.GetItems() enable you to select a specified number of items randomly from an input set:

The newRandom.ShuffleandRandomNumberGenerator.Shuffle<T>(Span<T>) methods let’s randomize the order of a span. These methods are valuable for mitigating training bias in machine learning, (so the first item isn’t necessarily training, and the last item isn’t necessarily test).

New Time Abstraction API

The newly introduced TimeProvider class and ITimer interface offer time abstraction functionality, facilitating the simulation of time in testing scenarios. The TimeProvider is an abstract class featuring numerous virtual functions, which makes it an ideal candidate for integration with mocking frameworks. This allows for seamless and comprehensive mocking of all its aspects. For example:

C

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

static DateTimeOffset AddNDaysToUtcNow(TimeProvider timeProvider, int nbDays) {

return timeProvider.GetUtcNow().AddDays(nbDays);

}

[Test]

public void Test_AddNDaysToNow() {

var ttp = new TestTimeProvider(new DateTimeOffset(new DateTime(2023,10,30,0,0,0)));

var result = AddNDaysToUtcNow(ttp, 5);

Assert.IsTrue(result.Year == 2023);

Assert.IsTrue(result.Month == 11);

Assert.IsTrue(result.Day == 4);

}

class TestTimeProvider : TimeProvider {

private readonly DateTimeOffset m_UtcNow;

public TestTimeProvider(DateTimeOffset utcNow) { this.m_UtcNow = utcNow; }

public override DateTimeOffset GetUtcNow() { return m_UtcNow; }

}

Let’s underline this remark from a Microsoft engineer:

“At the end of the day, we expect almost no one will use anything other than TimeProvider.Systemin production usage. Unlike many abstractions then, this one is special: it exists purely for testability”.

Notice that you can also harness time abstraction to simulate Task operations that depend on time progression, such as Task.Delay() and Task.WaitAsync().

These time abstractions were highly anticipated, following years of debates and discussions.

New Types that can Improve Performance in Various Situations

  • .NET 8 offers the new System.Collections.Frozen namespace. It contains the new collection classes FrozenSet<T> and FrozenDictionary<TKey,TValue>. The Frozen qualifier means that the collections are immutable: it cannot be changed once created. Internally the implementation does harness this requirement to allows for faster enumeration and faster lookup operations like Contains() or TryGetValue(). These new frozen collections prove particularly valuable in scenarios where collections are initially populated and subsequently endure for the entire lifecycle of a long-lived application.

1

2

3

4

5

6

7

8

List<int> list = [1, 2, 3, 4];

FrozenSet<int> frozenSet = list.ToFrozenSet();

Assert.IsTrue(frozenSet.Contains(4)); // Faster because the set is immutable

HashSet<int> hashSet = list.ToHashSet();

hashSet.Add(5);

Assert.IsTrue(hashSet.Contains(2)); // Slower because we can modify the set

  • The new class System.Buffers.SearchValues<T> is optimized for scenarios where a consistent set of values is frequently employed for runtime searches like for example in the implementation of String.IndexOfAny(char[]). When you create a SearchValues<T>instance, all the essential data required to optimize future searches is computed in advance, streamlining the process.
  • The new class System.Text.CompositeFormat proves invaluable for optimizing format strings -like "First Name:{0} Last Name: {1}"– not known at compile time. While there is an initial overhead in tasks such as string parsing, this proactive approach significantly reduces the computational burden in subsequent uses, enhancing performance and efficiency.

UTF8 Formatting

To enable the generation of a string-like representation of your type into a destination span, implement the recently introduced IUtf8SpanFormattable interface for your type:

C

1

2

3

public interface IUtf8SpanFormattable {

bool TryFormat(Span<byte> utf8Destination, out int bytesWritten, ReadOnlySpan<char> format, IFormatProvider? provider);

}

This interface is similar to ISpanFormattable. It is designed specifically for UTF-8 and Span<byte>, as opposed to UTF-16 and Span<char>.

In .NET 8 all primitive types (and more) implement this interface: Byte,Complex,Char,DateOnly,DateTime,DateTimeOffset,Decimal,Double,Guid,Half,IPAddress,IPNetwork,Int16,Int32,Int64,Int128,IntPtr,NFloat,SByte,Single,Rune,TimeOnly,TimeSpan,UInt16,UInt32,UInt64,UInt128,UIntPtr, andVersion.

Stream-based ZipFile methods

It is now feasible to compress files from a directory using a stream without the need to cache them in a temporary file. This allows for direct management of the compression result in memory. These new APIs prove beneficial in scenarios where disk space is limited, as they eliminate the need to utilize the disk as an intermediate step. Here are the new APIs:

C

1

2

3

4

5

6

7

8

9

10

11

12

13

namespace System.IO.Compression;

public static partial class ZipFile

{

public static void CreateFromDirectory(string sourceDirectoryName, Stream destination);

public static void CreateFromDirectory(string sourceDirectoryName, Stream destination, CompressionLevel compressionLevel, bool includeBaseDirectory);

public static void CreateFromDirectory(string sourceDirectoryName, Stream destination, CompressionLevel compressionLevel, bool includeBaseDirectory, Encoding? entryNameEncoding);

public static void ExtractToDirectory(Stream source, string destinationDirectoryName) { }

public static void ExtractToDirectory(Stream source, string destinationDirectoryName, bool overwriteFiles) { }

public static void ExtractToDirectory(Stream source, string destinationDirectoryName, Encoding? entryNameEncoding) { }

public static void ExtractToDirectory(Stream source, string destinationDirectoryName, Encoding? entryNameEncoding, bool overwriteFiles) { }

}

Support for the Intel AVX-512 instruction set

.NET Core 3.0 proposed support for SIMD by incorporating platform-specific hardware intrinsics APIs for x86/x64. Subsequently, .NET 5 extended this support to Arm64, and with the advent of .NET 7, cross-platform hardware intrinsics were introduced. .NET 8 further enhances SIMD capabilities by introducing Vector512<T> and extending support for Intel Advanced Vector Extensions 512 (AVX-512) instructions.

In particular, .NET 8 introduces support for the following key AVX-512 features:

  1. 512-bit vector operations.
  2. An additional 16 SIMD registers.
  3. Additional instructions are available for 128-bit, 256-bit, and 512-bit vectors.

Moreover, even without explicitly utilizing Vector512-specific or Avx512F-specific instructions in your code, you are likely to benefit from the improved AVX-512 support. The JIT compiler can leverage the extra registers and instructions implicitly when you use Vector128<T> or Vector256<T>.

Finally, note that if you have AVX-512 compatible hardware, Vector512.IsHardwareAccelerated will now return true.

Cryptography

.NET 8 now proposes support for SHA-3 hashing primitives. SHA-3 is currently compatible with Linux running OpenSSL 1.1.1 or later, and Windows 11 Build 25324 or later. Existing APIs offering SHA-2 now include their SHA-3 counterparts encompassing SHA3_256,SHA3_384, andSHA3_512 for hashing;HashAlgorithmName.SHA3_256,HashAlgorithmName.SHA3_384, andHashAlgorithmName.SHA3_512 for hashing where the algorithm is configurable; HMACSHA3_256,HMACSHA3_384, andHMACSHA3_512for HMAC; andRSAEncryptionPadding.OaepSHA3_256,RSAEncryptionPadding.OaepSHA3_384, andRSAEncryptionPadding.OaepSHA3_512for RSA OAEP encryption.

Summing it up, .NET 8 stands as a substantial leap forward, introducing a plethora of new features and enhancements. The new APIs and capabilities are well-suited to ensure the competitiveness and security of your code over the next three years.

.NET 8 Top 10 New Features - NDepend Blog (2024)
Top Articles
Latest Posts
Article information

Author: Lidia Grady

Last Updated:

Views: 6686

Rating: 4.4 / 5 (65 voted)

Reviews: 80% of readers found this page helpful

Author information

Name: Lidia Grady

Birthday: 1992-01-22

Address: Suite 493 356 Dale Fall, New Wanda, RI 52485

Phone: +29914464387516

Job: Customer Engineer

Hobby: Cryptography, Writing, Dowsing, Stand-up comedy, Calligraphy, Web surfing, Ghost hunting

Introduction: My name is Lidia Grady, I am a thankful, fine, glamorous, lucky, lively, pleasant, shiny person who loves writing and wants to share my knowledge and understanding with you.