Introduction aux types d’enregistrements en C#

Un enregistrement en C# est une classe ou un struct qui fournit une syntaxe et un comportement spéciaux pour l’utilisation de modèles de données. Le modificateur record indique au compilateur de synthétiser des membres utiles pour les types dont le rôle principal stocke des données. Ces membres incluent une surcharge et des membres qui prennent en charge l’égalité des valeurs ToString().

Quand utiliser des enregistrements

Envisagez d’utiliser un enregistrement à la place d’une classe ou d’un struct dans les scénarios suivants :

  • Vous souhaitez définir un modèle de données qui dépend de l’égalité des valeurs.
  • Vous souhaitez définir un type pour lequel les objets sont immuables.

Égalité des valeurs

Pour les enregistrements, l’égalité des valeurs signifie que deux variables d’un type d’enregistrement sont égales si les types correspondent et que toutes les valeurs de propriété et de champ correspondent. Pour d’autres types de référence tels que les classes, l’égalité signifie l’égalité des références. Autrement dit, deux variables d’un type de classe sont égales si elles font référence au même objet. Les méthodes et les opérateurs qui déterminent l’égalité de deux instances d’enregistrement utilisent l’égalité des valeurs.

Tous les modèles de données ne fonctionnent pas correctement avec l’égalité des valeurs. Par exemple, Entity Framework Core dépend de l’égalité des références pour s’assurer qu’il n’utilise qu’une seule instance d’un type d’entité pour ce qui est conceptuellement une seule entité. Pour cette raison, les types d’enregistrements ne sont pas appropriés pour une utilisation en tant que types d’entités dans Entity Framework Core.

Immuabilité

Un type immuable est un type qui vous empêche de modifier les valeurs de propriété ou de champ d’un objet après son instanciation. L’immuabilité peut être utile lorsque vous avez besoin d’un type thread-safe ou que vous dépendez d’un code de hachage restant le même dans une table de hachage. Les enregistrements fournissent une syntaxe concise pour la création et l’utilisation de types immuables.

L’immuabilité n’est pas appropriée pour tous les scénarios de données. Entity Framework Core, par exemple, ne prend pas en charge la mise à jour avec des types d’entités immuables.

Différences entre les enregistrements et les classes et les structs

La même syntaxe qui déclare et instancie des classes ou des structs peut être utilisée avec des enregistrements. Remplacez simplement le mot clé class par record, ou utilisez record struct au lieu de struct. De même, la syntaxe utilisée pour exprimer les relations d’héritage est prise en charge par les classes d’enregistrement. Les enregistrements diffèrent des classes de la manière suivante :

  • Vous pouvez utiliser des paramètres positionnels dans un constructeur principal pour créer et instancier un type avec des propriétés immuables.
  • Les mêmes méthodes et opérateurs qui indiquent l’égalité de référence ou l’inégalité dans les classes (par exemple Object.Equals(Object) et ==), indiquent l’égalité ou l’inégalité de valeur dans les enregistrements.
  • Vous pouvez utiliser une expressionwith pour créer une copie d’un objet immuable avec de nouvelles valeurs dans les propriétés sélectionnées.
  • La méthode ToString d’un enregistrement crée une chaîne mise en forme qui affiche le nom de type d’un objet et les noms et valeurs de toutes ses propriétés publiques.
  • Un enregistrement peut hériter d’un autre enregistrement. Un enregistrement ne peut pas hériter d’une classe et une classe ne peut pas hériter d’un enregistrement.

Les structs d’enregistrement diffèrent des structs : le compilateur synthétise les méthodes d’égalité et ToString. Le compilateur synthétise une méthode Deconstruct pour les structs d’enregistrement positionnel.

Le compilateur synthétise une propriété init seule publique pour chaque paramètre de constructeur principal dans un record class. Dans un record struct, le compilateur synthétise une propriété en lecture-écriture publique. Le compilateur ne crée pas de propriétés pour les paramètres de constructeur principal dans les types class et struct qui n’incluent pas de modificateur record.

Exemples

L’exemple suivant définit un enregistrement public qui utilise des paramètres positionnels pour déclarer et instancier un enregistrement. Il affiche ensuite le nom de type et les valeurs de propriété :


public record Person(string FirstName, string LastName);

public static class Program
{
    public static void Main()
    {
        Person person = new("Nancy", "Davolio");
        Console.WriteLine(person);
        // output: Person { FirstName = Nancy, LastName = Davolio }
    }

}

L’exemple suivant illustre l’égalité des valeurs dans les enregistrements :

public record Person(string FirstName, string LastName, string[] PhoneNumbers);
public static class Program
{
    public static void Main()
    {
        var phoneNumbers = new string[2];
        Person person1 = new("Nancy", "Davolio", phoneNumbers);
        Person person2 = new("Nancy", "Davolio", phoneNumbers);
        Console.WriteLine(person1 == person2); // output: True

        person1.PhoneNumbers[0] = "555-1234";
        Console.WriteLine(person1 == person2); // output: True

        Console.WriteLine(ReferenceEquals(person1, person2)); // output: False
    }
}

L’exemple suivant illustre l’utilisation d’une expression with pour copier un objet immuable et modifier l’une des propriétés :

public record Person(string FirstName, string LastName)
{
    public required string[] PhoneNumbers { get; init; }
}

public class Program
{
    public static void Main()
    {
        Person person1 = new("Nancy", "Davolio") { PhoneNumbers = new string[1] };
        Console.WriteLine(person1);
        // output: Person { FirstName = Nancy, LastName = Davolio, PhoneNumbers = System.String[] }

        Person person2 = person1 with { FirstName = "John" };
        Console.WriteLine(person2);
        // output: Person { FirstName = John, LastName = Davolio, PhoneNumbers = System.String[] }
        Console.WriteLine(person1 == person2); // output: False

        person2 = person1 with { PhoneNumbers = new string[1] };
        Console.WriteLine(person2);
        // output: Person { FirstName = Nancy, LastName = Davolio, PhoneNumbers = System.String[] }
        Console.WriteLine(person1 == person2); // output: False

        person2 = person1 with { };
        Console.WriteLine(person1 == person2); // output: True
    }
}

Pour plus d’informations, consultez Enregistrements (référence C#).

Spécification du langage C#

Pour plus d'informations, voir la spécification du langage C#. La spécification du langage est la source de référence pour la syntaxe C# et son utilisation.