Initialisation des systèmes...

Baptiste.Dev
Retour aux notes
LangagesIntermédiaireSérie : C# / .NET

C# : Les records

Immutabilité, comparaison par valeur, with-expressions - les records pour des données propres en C#.

3 min de lecture
Mis à jour il y a 4 mois
c#csharprecordimmutabilitécomparaisonC# 9

C# : Les records

Introduits en C# 9, les records sont des types conçus pour représenter des données immuables. Ils ressemblent aux classes mais avec des comportements intégrés : comparaison par valeur, ToString() automatique, copie simplifiée.


# Pourquoi les records ?

Avec une classe classique, deux objets avec les mêmes données ne sont pas égaux par défaut - C# compare les références, pas les valeurs :

class Personne
{
    public string Nom { get; init; }
    public int Age { get; init; }
}
 
Personne a = new Personne { Nom = "Alice", Age = 30 };
Personne b = new Personne { Nom = "Alice", Age = 30 };
 
Console.WriteLine(a == b);  // false ! Ce sont deux objets différents

Les records résolvent ça. Deux records avec les mêmes valeurs sont égaux :

record Personne(string Nom, int Age);
 
Personne a = new Personne("Alice", 30);
Personne b = new Personne("Alice", 30);
 
Console.WriteLine(a == b);  // true !

# Syntaxe

Syntaxe positionnelle (la plus courante)

record Personne(string Nom, int Age);

Une seule ligne. Le compilateur génère automatiquement :

  • Les propriétés Nom et Age en lecture seule (init)
  • Un constructeur avec les deux paramètres
  • Equals() et == qui comparent par valeur
  • GetHashCode() cohérent avec l'égalité
  • ToString() lisible : Personne { Nom = Alice, Age = 30 }
  • La méthode Deconstruct() pour le pattern matching

Syntaxe complète

Si tu as besoin de plus de contrôle :

record Personne
{
    public string Nom { get; init; }
    public int Age { get; init; }
    public string Email { get; init; }
 
    // Propriété calculée
    public bool EstMajeur => Age >= 18;
}

# Copie avec modification (with)

Les records sont immuables - on ne modifie pas un record, on en crée un nouveau avec les changements souhaités :

record Personne(string Nom, int Age);
 
Personne alice = new Personne("Alice", 30);
Personne aliceAgee = alice with { Age = 31 };
 
Console.WriteLine(alice);       // Personne { Nom = Alice, Age = 30 }
Console.WriteLine(aliceAgee);   // Personne { Nom = Alice, Age = 31 }

with copie toutes les propriétés et ne change que celles spécifiées. L'original n'est jamais modifié.


# Record class vs record struct

Par défaut, un record est un type référence (comme une classe). Depuis C# 10, on peut aussi créer des record structs :

// Record class (défaut)  -  type référence, heap
record Personne(string Nom, int Age);
 
// Record struct  -  type valeur, stack
record struct Point(double X, double Y);
record (class)record structreadonly record struct
StockageHeapStackStack
CopiePar référencePar valeurPar valeur
Propriétésget/init (immuables)get/set (mutables)get (immuables)
withOuiOuiOui
Égalité par valeurOuiOuiOui

Attention : un record struct a des propriétés mutables par défaut (get/set). Si tu veux l'immutabilité, utilise readonly record struct.


# Héritage de records

Les records supportent l'héritage (uniquement record -> record) :

record Personne(string Nom, int Age);
record Etudiant(string Nom, int Age, string Universite) : Personne(Nom, Age);
 
Etudiant e = new Etudiant("Alice", 20, "Paris-Saclay");
Console.WriteLine(e);  // Etudiant { Nom = Alice, Age = 20, Universite = Paris-Saclay }

L'égalité prend en compte le type : un Personne et un Etudiant avec les mêmes Nom et Age ne sont pas égaux.


# Quand utiliser un record

Les records sont le bon choix pour :

  • Les DTO (Data Transfer Objects) - données échangées entre couches
  • Les événements - record OrderPlaced(Guid OrderId, DateTime At)
  • Les clés composites - l'égalité par valeur évite les bugs
  • Tout objet qui représente une donnée plutôt qu'une entité avec comportement

La règle simple : si l'objet est défini par ce qu'il contient (ses données) plutôt que par ce qu'il est (son identité), c'est un record.


# La suite

  • Les enums - énumérations et constantes nommées