C# 12 et .NET 8 : Les nouveautés à connaître en 2026

C# continue d'évoluer. Voici les fonctionnalités de C# 12 que j'utilise quotidiennement et qui améliorent vraiment la productivité.

Primary Constructors (Classes)

Enfin disponible pour les classes (pas seulement les records) ! Plus besoin de boilerplate pour l'injection de dépendances :

Avant C# 12

public class ProductService
{
    private readonly IProductRepository _repository;
    private readonly ILogger<ProductService> _logger;

    public ProductService(IProductRepository repository, ILogger<ProductService> logger)
    {
        _repository = repository;
        _logger = logger;
    }

    public async Task<Product> GetById(int id)
    {
        _logger.LogInformation("Getting product {Id}", id);
        return await _repository.GetByIdAsync(id);
    }
}

Avec C# 12

public class ProductService(IProductRepository repository, ILogger<ProductService> logger)
{
    public async Task<Product> GetById(int id)
    {
        logger.LogInformation("Getting product {Id}", id);
        return await repository.GetByIdAsync(id);
    }
}

Moins de code, même fonctionnalité. Les paramètres sont accessibles dans toute la classe.

Collection Expressions

Une syntaxe unifiée pour créer des collections :

// Avant
int[] numbers = new int[] { 1, 2, 3 };
List<string> names = new List<string> { "Alice", "Bob" };
Span<int> span = stackalloc int[] { 1, 2, 3 };

// Avec C# 12
int[] numbers = [1, 2, 3];
List<string> names = ["Alice", "Bob"];
Span<int> span = [1, 2, 3];

Spread operator

int[] first = [1, 2, 3];
int[] second = [4, 5, 6];
int[] combined = [..first, ..second]; // [1, 2, 3, 4, 5, 6]

// Pratique pour les options par défaut
string[] defaultTags = ["important"];
string[] userTags = ["urgent", "review"];
string[] allTags = [..defaultTags, ..userTags];

Alias de types (using)

Vous pouvez maintenant créer des alias pour n'importe quel type :

using Point = (int X, int Y);
using UserId = System.Guid;
using ProductList = System.Collections.Generic.List<Product>;

public class Example
{
    public Point Location { get; set; } = (0, 0);
    public UserId Id { get; set; } = UserId.NewGuid();
    public ProductList Products { get; set; } = [];
}

Améliore la lisibilité, surtout pour les tuples et types génériques complexes.

Default Lambda Parameters

// Paramètres par défaut dans les lambdas
var greet = (string name = "World") => $"Hello, {name}!";

Console.WriteLine(greet());        // "Hello, World!"
Console.WriteLine(greet("Alice")); // "Hello, Alice!"

Inline Arrays

Pour les scénarios haute performance :

[InlineArray(10)]
public struct Buffer
{
    private int _element;
}

// Utilisation
var buffer = new Buffer();
buffer[0] = 42;
buffer[1] = 43;

Évite les allocations heap pour les petits tableaux de taille fixe.

.NET 8 : Améliorations performance

Frozen Collections

using System.Collections.Frozen;

// Création (une seule fois, coûteux)
FrozenDictionary<string, int> lookup = new Dictionary<string, int>
{
    ["one"] = 1,
    ["two"] = 2,
    ["three"] = 3
}.ToFrozenDictionary();

// Lecture (très rapide)
int value = lookup["two"];
Conseil migration : Si vous êtes sur .NET 6 ou 7, la migration vers .NET 8 est généralement smooth. Les gains de performance justifient l'effort, surtout pour les applications ASP.NET Core.

Conclusion

C# 12 apporte des améliorations de qualité de vie significatives. Les primary constructors et collection expressions sont mes préférées - elles réduisent le boilerplate sans sacrifier la lisibilité.

Besoin d'aide pour moderniser votre codebase C# ? Contactez-moi.

Davy Abderrahman

Davy Abderrahman

Expert C#/.NET certifié Microsoft MCSD. Passionné par les évolutions du langage depuis C# 1.0.

En savoir plus