Attributes for record auto-property in C#9
O record
ako novom spôsobe pre jednoduché a elegantné vytváranie immutable objektov sa popísalo veľa. Napríklad tu.
Jednou zo zaujímavých vlastností je možnosť využiť syntaxt nazývanú positional records. V tomto prípade môžeme definovať jednotlivé property priamo v konštruktore.
public record Person(string FirstName, string LastName);
Problém môže nastať, pokiaľ daným property chceme nastaviť atribút. Napríklad [JsonProperty]
.
Prvoplánovo to môžeme skúsiť nasledovne.
public record Person([JsonProperty("name")]string FirstName, string LastName);
Keby sme sa však pozreli na skutočne vygenerovaný kód, tak uvidíme niečo nasledovné:
// Simplied code
public class Person : IEquatable<Person>
{
public string FirstName
{
get;
init;
}
public string LastName
{
get;
init;
}
public Person([JsonProperty("name")] string FirstName, string LastName)
{
this.FirstName = FirstName;
this.LastName = LastName;
}
}
A to nie je to čo sme chceli. My sme chceli nastaviť ten atribút pre property, nie pre parameter konštruktora. Samozrejme môžeme použiť tradičnú syntaxt s deklaráciou properties.
public record Person
{
[JsonProperty("name")]
public string FirstName { get; init; }
public string LastName { get; init; }
public Person(string firstName, string lastName)
=> (FirstName, LastName) = (firstName, lastName);
}
Ale čo keď naozaj chceme použiť positional records?
Riešením je použitie property:
.
public record Person([property:JsonProperty("name")]string FirstName, string LastName);
Attributes can be applied to the synthesized auto-property and its backing field by using property: or field: targets for attributes syntactically applied to the corresponding record parameter. Viď špecifikácia.
Pokiaľ si to pozrieme napríklad cez ILSpy tak uvidíme niečo nasledovné.
// Simplied code
public class Person : IEquatable<Person>
{
[JsonProperty("name")]
public string FirstName
{
get;
init;
}
public string LastName
{
get;
init;
}
public Person(string FirstName, string LastName)
{
this.FirstName = FirstName;
this.LastName = LastName;
}
}
A to je to čo sme chceli dosiahnúť. (Teda aspoň ja 😉)