Dot.Blog

C#, XAML, WinUI, WPF, Android, MAUI, IoT, IA, ChatGPT, Prompt Engineering

Nouveautés de C# 13 et 14

C# bouge en permanence... Si l'on cumule toutes les modifications apportées depuis sa naissance on peut penser qu'il grossit de trop. Mais à bien y regarder la plupart des améliorations vont majoritairement dans le sens d'une utilisation plus simple et plus naturelle du langage. Voyons ce que C# 13 et bientôt 14 (en preview) nous apportent...


Nouveautés de C# 13 et 14 : explications simples et exemples

C# continue d’évoluer chaque année avec de nouvelles fonctionnalités qui simplifient le code, le rendent plus lisible, plus sûr, ou plus performant. Si vous êtes un développeur habitué aux bases du langage, pas d’inquiétude : les nouveautés des versions 13 et 14 peuvent vraiment vous aider dans votre quotidien sans tout bouleverser.

Je vous propose ici une explication claire et progressive des nouveautés, pour les versions 13 actuelle et 14 à venir.


🌟 C# 13 — Les nouveautés pas à pas

1. params fonctionne maintenant avec des listes ou des tableaux modernes

Avant, on ne pouvait utiliser params qu’avec des tableaux (int[]). Maintenant, on peut aussi l’utiliser avec des objets comme Span<>, ce qui permet d’écrire des fonctions plus flexibles.

void Affiche(params ReadOnlySpan<int> nombres)
{
    foreach (var n in nombres)
        Console.WriteLine(n);
}

Affiche(1, 2, 3);

👉 Ce que ça change pour vous : vous pouvez appeler cette fonction avec n’importe quelle source de données, pas seulement un tableau.


2. Nouveau système de verrouillage (Lock) plus moderne

Avant, on utilisait lock(obj) avec un objet, souvent un peu bricolé. Maintenant, il y a un nouveau type spécial (System.Threading.Lock) conçu spécialement pour ça.

private Lock monVerrou = new();

void Travail()
{
    lock (monVerrou)
    {
        // partie protégée
    }
}

👉 Ce que ça change : plus besoin d’utiliser des objets comme verrou, on a un outil fait pour ça.


3. Nouveau caractère d’échappement \e

On peut maintenant écrire \e pour le caractère "ESC" dans les chaînes (utile pour les terminaux, les couleurs, etc.)

Console.WriteLine("\e[31mTexte rouge\e[0m");

👉 Plus lisible que \u001B ou \x1b.


4. Les groupes de méthodes sont mieux compris

Avant, il fallait parfois convertir une méthode en délégué avec une syntaxe verbeuse. Maintenant, C# comprend mieux ce que vous voulez faire.

Action a = Console.WriteLine; // plus besoin de préciser le type exact

👉 Le compilateur est plus intelligent, vous avez moins de code à écrire.


5. Vous pouvez utiliser ^ dans un initialiseur de tableau

L’opérateur ^ permet de compter depuis la fin d’un tableau. On peut maintenant l’utiliser dès l’initialisation.

int[] tableau = new int[5];
tableau[^1] = 42; // affecte la dernière case

👉 Utile pour les affectations inversées ou progressives.


6. ref et unsafe mieux gérés dans les méthodes async et yield

Si vous utilisez du code bas niveau (accès mémoire, pointeurs), vous avez désormais plus de liberté dans les méthodes asynchrones.

👉 Si vous ne faites pas de code avec Span<T>, ref, ou unsafe, vous pouvez ignorer cette nouveauté.


7. Les types spéciaux (ref struct) peuvent maintenant avoir des interfaces

Avant, un type ref struct (comme Span<T>) ne pouvait pas dire « j’implémente une interface ». Maintenant, si.

👉 Cela ne change pas votre quotidien sauf si vous faites du code très bas niveau ou des performances poussées.


8. Vous pouvez autoriser explicitement les ref struct dans les génériques

Avant, les génériques refusaient ce genre de types. Maintenant, on peut les autoriser.

T Copier<T>(T valeur) where T : allows ref struct => valeur;

👉 Encore une fois, surtout utile si vous manipulez des types comme Span<T>.


9. Les propriétés peuvent être partial

Les générateurs de code (comme ceux utilisés en MVVM) peuvent désormais générer une partie d’une propriété, et vous l’autre.

public partial int Compteur { get; set; }

👉 Pratique si vous utilisez des outils comme INotifyPropertyChanged ou un framework MVVM.


10. On peut définir une surcharge "préférée"

Grâce à un attribut, vous pouvez indiquer au compilateur quelle méthode choisir par défaut si plusieurs sont possibles.

👉 Intéressant pour ceux qui créent des bibliothèques.


🌟 C# 14 — Encore plus de confort (prévu fin 2025)

1. Propriétés d’extension (et autres membres)

Avant, les méthodes d’extension étaient possibles, mais pas les propriétés. Maintenant, on peut aussi faire :

public static class Extensions {
    public static int Longueur(this string texte) => texte.Length;
}

👉 Ça permet d’écrire des codes plus lisibles, comme si la méthode faisait partie du type.


2. ??= plus puissant

On peut maintenant utiliser ??= même dans des expressions plus complexes.

maVariable?.SousObjet ??= new SousObjet();

👉 Cela vous évite d’écrire des if (x == null) partout.


3. nameof fonctionne avec des types génériques non précisés

Avant, nameof(List<>) ne fonctionnait pas. Maintenant, oui.

Console.WriteLine(nameof(List<>)); // Affiche "List"

👉 Petit plus pour les messages d’erreurs ou la génération de code.


4. Conversions plus simples pour Span<T>

Le passage d’un tableau à un Span ou ReadOnlySpan se fait sans cast explicite.

int[] données = {1, 2, 3};
Span<int> span = données;

👉 Plus besoin de convertir manuellement, le compilateur s’en charge.


5. Lambdas plus puissantes avec ref, in, etc.

On peut écrire des fonctions anonymes qui utilisent des paramètres spéciaux.

Func<ref int, int> doubler = (ref int x) => x * 2;

👉 Utile pour ceux qui font du code très optimisé, sinon pas indispensable.


6. On peut accéder au champ auto-généré d’une propriété

C# crée automatiquement un champ pour les propriétés avec { get; set; }. On peut maintenant y accéder via le mot field.

public int Valeur {
  get => field;
  set {
    if (value < 0) throw new();
    field = value;
  }
}

👉 Vous pouvez contrôler ce qui se passe tout en gardant une propriété auto.


7. partial aussi pour les constructeurs et événements

Les générateurs de code pourront aussi vous aider à créer des constructeurs ou des événements, comme ils le font déjà pour les méthodes.


✅ Conclusion

Même si vous utilisez surtout les bases de C#, les versions 13 et 14 proposent des améliorations qui peuvent rendre votre code :

  • Plus simple

  • Plus lisible

  • Moins répétitif

  • Plus sûr (verrouillage, ref, Span)

Je vous recommande de tester petit à petit ces nouveautés dans de petits projets ou outils internes. Pas besoin d’adopter tout d’un coup — mais certaines améliorations (comme params plus souple, field, partial property, etc.) peuvent vous faire gagner du temps très vite.

Un projet exemple utilisant les nouveautés

Ce projet exemple concret, montre comment les nouveautés de C# 13 et 14 peuvent être mises à profit dans une application simple.


Un projet console simple avec C# 13 et 14

Objectif

Créer une petite TODO list avec :

  • Des propriétés partagées (partial property),

  • Des extensions (propriétés d’extension),

  • L’usage de params ReadOnlySpan<T> pour loguer,

  • Un code lisible, moderne, mais accessible.


1. Propriétés partial avec accès au champ field

Permet de définir une propriété dont l’implémentation est répartie dans plusieurs fichiers, tout en accédant directement au champ généré.

Comment cela s’écrivait avant ? Il fallait créer manuellement un champ privé et implémenter totalement la propriété.

Maintenant on fera :

public partial class Tache
{
    public string Description { get; set; }

    public partial DateTime CreeLe { get; set; } = DateTime.Now;

    public bool EstTerminee { get; set; }

    public void Terminer() => EstTerminee = true;
}

public partial class Tache
{
    public partial DateTime CreeLe {
        get => field;
        set {
            if (value > DateTime.Now)
                throw new ArgumentException("Date dans le futur");
            field = value;
        }
    }
}

Qu’est-ce que cela change pour moi ? On peut garder la simplicité des propriétés automatiques tout en personnalisant le comportement, de façon souple et propre.


2. Propriétés d’extension

On peut ajouter des propriétés à des types existants sans les modifier directement.

Comment cela s’écrivait avant ? On ne pouvait écrire que des méthodes d’extension, pas des propriétés.

Maintenant on fera :

public static class TacheExtensions
{
    public static string Resume(this Tache t)
        => $"{(t.EstTerminee ? "[X]" : "[ ]")} {t.Description} (créée le {t.CreeLe:dd/MM/yyyy})";

    public static bool EstVide(this IEnumerable<Tache> liste)
        => !liste.Any();
}

Qu’est-ce que cela change pour moi ? Vous pouvez simplifier l’usage des objets et ajouter des fonctionnalités comme si elles étaient natives.


3. Utilisation de params ReadOnlySpan<string> pour un logging flexible

Permet d’écrire une méthode Log acceptant une liste souple de chaînes, sans création de tableau explicite.

Comment cela s’écrivait avant ? Il fallait passer un tableau de chaînes manuellement.

Log(new string[] { "Message1", "Message2" });

Maintenant on fera :

static void Log(params ReadOnlySpan<string> messages)
{
    foreach (var m in messages)
        Console.WriteLine($"[LOG] {m}");
}

Log("Tâche créée", "Utilisateur: anonyme", $"Heure: {DateTime.Now}");

Qu’est-ce que cela change pour moi ? Vous écrivez moins de code pour faire un log multiple et pouvez passer des données diverses plus facilement.


4. Programme principal intégrant les nouveautés

Utilise les extensions et les nouvelles syntaxes pour un petit gestionnaire de tâches.

Comment cela s’écrivait avant ? Il aurait fallu plus de code verbeux, sans propriétés partielles ni extensions propres.

Maintenant on écrira :

List<Tache> taches = new();

while (true)
{
    Console.WriteLine("\n--- Mini To-Do ---");
    Console.WriteLine("1. Ajouter une tâche");
    Console.WriteLine("2. Afficher les tâches");
    Console.WriteLine("3. Quitter");
    Console.Write("Choix : ");
    var choix = Console.ReadLine();

    switch (choix)
    {
        case "1":
            Console.Write("Description : ");
            var desc = Console.ReadLine();
            if (!string.IsNullOrWhiteSpace(desc))
                taches.Add(new Tache { Description = desc });
            break;

        case "2":
            if (taches.EstVide())
                Console.WriteLine("Aucune tâche");
            else
                foreach (var t in taches)
                    Console.WriteLine(t.Resume());
            break;

        case "3":
            return;
    }
}

Qu’est-ce que cela change pour moi ? Vous écrivez un programme plus clair, plus structuré, avec des extensions lisibles et des propriétés modernes, tout en restant dans une logique simple.


Conclusion du projet

Ce mini-projet illustre comment utiliser des nouveautés C# récentes sans quitter votre zone de confort. Ces ajouts vous permettent d’écrire du code plus propre, plus expressif et plus maintenable avec des efforts minimes. Adoptez-les progressivement selon vos besoins.

Conclusion globale

Mon but était ici de vous montrer qu'au-delà de l'impression qu'on peut avoir d'un langage qui ne cesse d'enfler sans limite, devenant de plus en plus long à apprendre et à maitriser, il y a une véritable progression vers plus de cohérence, plus de simplicité d'écriture. Certes cela demande de mettre à jour ses connaissances du langage. Cent fois sur le métier tu remettras ton ouvrage... Certaines personnes trouvent cela fatigant c'est vrai. Mais c'est le métier d'informaticien qui est ainsi fait, évoluant très vite et obligeant à une perpétuelle mise à jour des connaissances. D'autres métiers ne réclament pas tant d'efforts, c'est vrai. Mais c'est aussi la satisfaction d'un environnement en mouvement permanent qui donne à notre art un peu de piquant, créant un challenge avec soi-même plutôt motivant. On peut ne pas apprécier. Mais on peut aussi n'utiliser qu'un sous ensemble de C# et écrire du code parfaitement correct. Il n'y a ni concours ni compétition, laissons cela aux vaniteux qui bombent le torse à la machine à café parce qu'ils connaissent le dernier truc à la mode. Rappelez-vous que ce qui compte c'est avant tout d'être heureux car un informaticien triste, stressé, mal dans ses baskets ne produira jamais du bon code. Et ensuite visez la satisfaction de l'utilisateur final sans perdre de vue la maintenabilité de votre code. Tout le reste est philosophie.

Stay Tuned !

Faites des heureux, PARTAGEZ l'article !