Advanced C# 13 and .NET 9 Features for Expert .NET Engineers

Overview

With the release of C# 13 and .NET 9, modern applications can be made much more productive and efficient. This article will explore the advanced features of C# 13 and .NET 9 and demonstrate how to leverage these features for optimal performance in large-scale applications through complex code examples.

Extended Pattern Matching Enhancements

It introduces new patterns, such as list patterns, which allow powerful destructuring and matching of collections. These patterns make it easier to write concise, readable, and efficient code.

Code Example. Complex List Pattern Matching

Imagine you have a complex nested list structure and need to match and transform elements according to certain criteria:

    public static string MatchComplexPattern(List<int> numbers)
    {
        return numbers switch
        {
        [0, .., > 5] => "Starts with 0 and ends with a number greater than 5",
        [1, 2, 3, .. var rest] when rest.Contains(4) => "Starts with 1, 2, 3 and contains a 4 in the remaining list",
            _ => "No match found"
        };
    }

As an example

  • A list that starts with 0 and ends with a number greater than 5 is matched by [0, ..., > 5].
  • [1, 2, 3, .. var rest] destructures the list to determine if it starts with 1, 2, 3 and then checks rest.Contains(4) for the remaining elements.

Static Abstract Members in Interfaces

.NET 13 now allows interfaces to define static members, which facilitates polymorphism and generic programming by allowing interfaces to define static members that inheriting types must be implemented.

Code Example. Creating Generic Operations with Static Abstract Members

Imagine you are building a generic calculation library that requires different types to implement static operations:

namespace ExpertDotNetSoftwareEngineering;

public interface ICalculable<T>
 where T : ICalculable<T>
{
    static abstract T Add(T a, T b);
    static abstract T Subtract(T a, T b);
}
public struct ComplexNumber : ICalculable<ComplexNumber>
{
    public double Real { get; }
    public double Imaginary { get; }
    public ComplexNumber(double real, double imaginary) => (Real, Imaginary) = (real, imaginary);

    public static ComplexNumber Add(ComplexNumber a, ComplexNumber b) =>
        new ComplexNumber(a.Real + b.Real, a.Imaginary + b.Imaginary);

    public static ComplexNumber Subtract(ComplexNumber a, ComplexNumber b) =>
        new ComplexNumber(a.Real - b.Real, a.Imaginary - b.Imaginary);
}

Here's how it works

  • <ICalculableT> provides static abstract methods for addition and subtraction.
  • The ComplexNumber class implements these operations, so we can use complex numbers in calculations in a generic manner.

Improved Collections with C# 13

Several improvements to collections are made in .NET 9, particularly around immutable collections and efficient iteration. These are designed to reduce overhead when dealing with large datasets or highly concurrent scenarios.

Code Example. Using Immutable Array Operations in Multithreading

The new optimized immutable arrays can significantly reduce contention in multi-threaded applications. Here's an example:

using System.Collections.Immutable;

Console.WriteLine("Hello, from Ziggy Rafiq");

var numbers = ImmutableArray.CreateRange(Enumerable.Range(1, 1000000));

// Use parallel processing to calculate squares without modifying the original array
var squares = numbers.AsParallel().Select(x => x * x).ToImmutableArray();

// Output first ten squares
Console.WriteLine(string.Join(", ", squares. Take(10)));

As a result of these enhancements, ImmutableArray operations have been optimized for performance, allowing concurrent operations on large collections with minimal overhead.

Source Generators in .NET 9: Building Compile-Time Code

In .NET 9, you can still use source generators, a feature that allows you to generate code at compile time. Source generators are useful for generating boilerplate code, such as the boilerplate for data transfer objects (DTOs) and domain entities.

Code Example. Building a Source Generator for DTOs

Suppose you have a repetitive set of DTO classes that require a similar boilerplate. By generating common patterns at compile time, you can reduce redundancy.


namespace ExpertDotNetSoftwareEngineering;

[AttributeUsage(AttributeTargets.Class, Inherited = false)]
public sealed class AutoDtoAttribute : Attribute { }

Using a source generator, we can automatically generate equality members, ToStrings, and even serialization methods for any class marked with the [AutoDto] attribute:c

using Microsoft.CodeAnalysis;

namespace ExpertDotNetSoftwareEngineering;

public class AutoDtoGenerator : ISourceGenerator
{
    public void Initialize(GeneratorInitializationContext context) { }

    public void Execute(GeneratorExecutionContext context)
    {
        var compilation = context.Compilation;
        foreach (var syntaxTree in compilation.SyntaxTrees)
        {
            // Implementation of source generator to find [AutoDto] and inject members
            // Example implementation skipped for brevity
        }
    }
}

Standardizing DTO structures across a large codebase reduces code maintenance.

Improved Task Handling with Async Streams

In .NET 9, async streams have been improved, making it easier to process data in real-time applications.

Code Example. Streaming Data from an External API

Suppose you are streaming data from an external API and want to process it as it arrives:

public static async IAsyncEnumerable<string?> FetchDataAsync(string? apiUrlAddress = null)
    {
        if (string.IsNullOrEmpty(apiUrlAddress))
        {
            apiUrlAddress = _apiUrlAddress;
        }

        using var httpClient = new HttpClient();
        using var response = await httpClient.GetAsync(apiUrlAddress, HttpCompletionOption.ResponseHeadersRead);

        response.EnsureSuccessStatusCode();
        using var stream = await response.Content.ReadAsStreamAsync();
        using var reader = new StreamReader(stream);

        while (!reader.EndOfStream)
        {
            yield return await reader.ReadLineAsync();
        }
    }

    public static async Task ProcessDataAsync(string? apiUrlAddress = null)
    {
        if (string.IsNullOrEmpty(apiUrlAddress))
        {
            apiUrlAddress = _apiUrlAddress;
        }

        await foreach (var line in FetchDataAsync(apiUrlAddress))
        {
            Console.WriteLine(line);
        }
    }

The following code demonstrates

  • The ability to read lines from an HTTP stream without waiting for the entire payload to load.
  • Using async streams to process each line in real-time is ideal for handling large, continuous datasets.

Native AOT (Ahead-of-Time Compilation)

.NET 9 introduces Native AOT (Ahead-of-Time Compilation), which compiles .NET code to a standalone, self-contained binary. This feature reduces the size of .NET applications and improves startup time, making it an ideal choice for high-performance applications.

Code Example. Configuring a Console Application for Native AOT

To configure a .NET 9 console application for Native AOT, follow these steps:

Set the PublishAot property in your project file to true.

<PropertyGroup>
    <PublishAot>true</PublishAot>
</PropertyGroup>

Use the dotnet publish command to publish the application.

dotnet publish -c Release -r win-x64 --self-contained

Summary

With C# 13 and .NET 9, .NET Software Engineer Leads will have the tools they need to build high-performance, maintainable, and efficient applications. The C# 13 and .NET 9 languages cater to expert developers who work on complex applications, from enhanced pattern matching and static abstract members to optimized collection handling, async streams, and Native AOT.

If you have found this article useful, please click the link button and connect with me on LinkedIn: https://www.linkedin.com/in/ziggyrafiq/, I have also uploaded this article's code examples to my GitHub Repository: https://github.com/ziggyrafiq/advanced-csharp-dotnet9-guide


Similar Articles
Capgemini
Capgemini is a global leader in consulting, technology services, and digital transformation.