Définir deux fois une propriété dans un enregistrement
En C # 9, on peut définir une propriété avec le même nom dans un enregistrement à la fois dans son constructeur principal et dans son corps:
record Cat(int PawCount)
{
public int PawCount { get; init; }
}
Ce code se compile sans erreur.
Lors de l'initialisation d'une instance d'un tel enregistrement, la valeur fournie au constructeur est complètement ignorée:
Console.WriteLine(new Cat(4));
Console.WriteLine(new Cat(4) { PawCount = 1 });
impressions
Cat { PawCount = 0 }
Cat { PawCount = 1 }
Ce comportement est-il correct ou s'agit-il d'un bogue? Si c'est correct, quels sont les cas dans lesquels c'est utile?
Je m'attendais à ce que le compilateur rejette ce code avec une erreur telle que «Le type Cat
contient déjà une définition pour PawCount
» ou considère la propriété dans le constructeur et dans le corps de la même manière, en effectuant son initialisation à partir du constructeur. Cette dernière variante pourrait être utile pour fournir à la propriété un getter et / ou un initialiseur personnalisé sans avoir à réécrire toutes les propriétés de l'enregistrement de position dans son corps.
Le comportement réel n'a aucun sens pour moi.
Réponses
La bonne façon de procéder est:
record Cat(int PawCount)
{
public int PawCount { get; init; } = PawCount;
}
Ceci est utile car cela vous permet de faire par exemple la validation
record Cat(int PawCount)
{
private int _pawCount;
public int PawCount {
get => _pawCount;
init => _pawCount = value < 0 ? throw new ArgumentException() : value;
} = PawCount;
}
La spécification pour cela est ici: https://github.com/dotnet/csharplang/blob/master/proposals/csharp-9.0/records.md#members-of-a-record-type
Les membres sont synthétisés à moins qu'un membre avec une signature «correspondante» soit déclaré dans le corps de l'enregistrement ou qu'un membre concret accessible non virtuel avec une signature «correspondante» soit hérité. Deux membres sont considérés comme identiques s'ils ont la même signature ou s'ils sont considérés comme «masqués» dans un scénario d'héritage.
Ainsi, comme une propriété portant le même nom que le paramètre existe déjà, le compilateur ne synthétisera pas une PawCount
propriété, et ignore donc le paramètre en silence, sauf si vous l'utilisez vous-même explicitement.