Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
L’expression
Une with expression crée une copie de son opérande avec les propriétés et champs spécifiés modifiés. Utilisez la syntaxe d’initialiseur d’objet pour spécifier les membres à modifier et leurs nouvelles valeurs :
using System;
public class WithExpressionBasicExample
{
public record NamedPoint(string Name, int X, int Y);
public static void Main()
{
var p1 = new NamedPoint("A", 0, 0);
Console.WriteLine($"{nameof(p1)}: {p1}"); // output: p1: NamedPoint { Name = A, X = 0, Y = 0 }
var p2 = p1 with { Name = "B", X = 5 };
Console.WriteLine($"{nameof(p2)}: {p2}"); // output: p2: NamedPoint { Name = B, X = 5, Y = 0 }
var p3 = p1 with
{
Name = "C",
Y = 4
};
Console.WriteLine($"{nameof(p3)}: {p3}"); // output: p3: NamedPoint { Name = C, X = 0, Y = 4 }
Console.WriteLine($"{nameof(p1)}: {p1}"); // output: p1: NamedPoint { Name = A, X = 0, Y = 0 }
var apples = new { Item = "Apples", Price = 1.19m };
Console.WriteLine($"Original: {apples}"); // output: Original: { Item = Apples, Price = 1.19 }
var saleApples = apples with { Price = 0.79m };
Console.WriteLine($"Sale: {saleApples}"); // output: Sale: { Item = Apples, Price = 0.79 }
}
}
L’opérande de gauche d’une with expression peut être un type d’enregistrement. Il peut également s’agir d’un type de structure ou d’un type anonyme.
La documentation de référence du langage C# décrit la version la plus récente du langage C#. Il contient également la documentation initiale des fonctionnalités dans les préversions publiques pour la prochaine version du langage.
La documentation identifie toute fonctionnalité introduite en premier dans les trois dernières versions de la langue ou dans les préversions publiques actuelles.
Conseil / Astuce
Pour savoir quand une fonctionnalité a été introduite en C#, consultez l’article sur l’historique des versions du langage C#.
Le résultat d’une with expression a le même type d’exécution que l’opérande de l’expression, comme l’illustre l’exemple suivant :
using System;
public class InheritanceExample
{
public record Point(int X, int Y);
public record NamedPoint(string Name, int X, int Y) : Point(X, Y);
public static void Main()
{
Point p1 = new NamedPoint("A", 0, 0);
Point p2 = p1 with { X = 5, Y = 3 };
Console.WriteLine(p2 is NamedPoint); // output: True
Console.WriteLine(p2); // output: NamedPoint { X = 5, Y = 3, Name = A }
}
}
Lorsqu’un membre est un type de référence, la copie de ce membre copie uniquement la référence à cette instance de membre. La copie et l’opérande d’origine accèdent à la même instance de type référence. L’exemple suivant illustre ce comportement :
using System;
using System.Collections.Generic;
public class ExampleWithReferenceType
{
public record TaggedNumber(int Number, List<string> Tags)
{
public string PrintTags() => string.Join(", ", Tags);
}
public static void Main()
{
var original = new TaggedNumber(1, new List<string> { "A", "B" });
var copy = original with { Number = 2 };
Console.WriteLine($"Tags of {nameof(copy)}: {copy.PrintTags()}");
// output: Tags of copy: A, B
original.Tags.Add("C");
Console.WriteLine($"Tags of {nameof(copy)}: {copy.PrintTags()}");
// output: Tags of copy: A, B, C
}
}
Sémantique de copie personnalisée
Chaque type de classe d’enregistrement a un constructeur de copie. Un constructeur de copie est un constructeur avec un seul paramètre du type d’enregistrement conteneur. Il copie l’état de son argument dans une nouvelle instance d’enregistrement. Lorsque vous évaluez une with expression, elle appelle le constructeur de copie pour créer une instance d’enregistrement basée sur un enregistrement d’origine. Ensuite, il met à jour la nouvelle instance avec les modifications spécifiées. Par défaut, le compilateur synthétise le constructeur de copie. Pour personnaliser la sémantique de copie d’enregistrement, déclarez explicitement un constructeur de copie avec le comportement souhaité. L’exemple suivant met à jour l’exemple précédent avec un constructeur de copie explicite. Le nouveau comportement de copie copie les éléments de liste au lieu d’une référence de liste lorsqu’un enregistrement est copié :
using System;
using System.Collections.Generic;
public class UserDefinedCopyConstructorExample
{
public record TaggedNumber(int Number, List<string> Tags)
{
protected TaggedNumber(TaggedNumber original)
{
Number = original.Number;
Tags = new List<string>(original.Tags);
}
public string PrintTags() => string.Join(", ", Tags);
}
public static void Main()
{
var original = new TaggedNumber(1, new List<string> { "A", "B" });
var copy = original with { Number = 2 };
Console.WriteLine($"Tags of {nameof(copy)}: {copy.PrintTags()}");
// output: Tags of copy: A, B
original.Tags.Add("C");
Console.WriteLine($"Tags of {nameof(copy)}: {copy.PrintTags()}");
// output: Tags of copy: A, B
}
}
Vous ne pouvez pas personnaliser la sémantique de copie pour les types de structure.
Important
Dans les exemples précédents, toutes les propriétés sont indépendantes. Aucune des propriétés n’est calculée à partir d’autres valeurs de propriété. Une with expression copie d’abord l’instance d’enregistrement existante, puis modifie toutes les propriétés ou champs spécifiés dans l’expression with . Les propriétés calculées dans les record types doivent être calculées lors de l’accès, et non initialisées lors de la création de l’instance. Sinon, une propriété peut retourner la valeur calculée en fonction de l’instance d’origine, et non la copie modifiée. Pour plus d’informations, consultez l’article recordde référence sur les types.
Spécification du langage C#
Pour plus d’informations, consultez les sections suivantes de la note de proposition de fonctionnalité d’enregistrements :