C#9.0 recordのプロパティに属性・XMLドキュメントコメントを付ける

2 min read読了の目安(約2500字

時々忘れるのでメモです。

positional records について

C#9.0の新機能の目玉であるrecordですが、positional records (位置指定レコード) と呼ばれる書き方によってプロパティ定義を省略できるようになりました。

// positional records 
public record Person(string FirstName, string LastName, int Age);

// 上はこれと同じ
public record Person
{
    public string FirstName { get; }
    public string LastName { get; }
    public int Age { get; }
    
    public Person(string firstName, string lastName, int age)
        => (FirstName, LastName, Age) = (firstName, lastName, age);
}

属性

このpositional recordsの時に、プロパティに対し属性を付けたい時どうするか?

[property: XXX] のようにします。属性を付ける典型例としてJSONシリアライズ用のクラスの例を載せました。

Newtonsoft.Json

public record Person(
    [property: JsonProperty("first_name", Required = Required.DisallowNull)] string FirstName,
    [property: JsonProperty("last_name", Required = Required.Always)] int LastName, 
    [property: JsonIgnore] int Age);

System.Text.Json

public record Person(
    [property: JsonPropertyName("first_name")] string FirstName,
    [property: JsonPropertyName("last_name")] int LastName, 
    [property: JsonIgnore] int Age);

DataContractJsonSerializer

[DataContract]
public record Person(
    [property: DataMember(Name = "first_name")] string FirstName,
    [property: DataMember(Name = "last_name")] int LastName, 
    [property: IgnoreDataMember] int Age);

XMLドキュメントコメント

属性同様に、プロパティのXMLドキュメントコメントをどう付けるか、私はrecordを実戦投入してみて課題になりました。

以下のURL先によると、<param>をrecordの上で定義すれば良いということになり、 Visual Studio 16.9 以降 / .NET SDK 5.0.200 以降 で有効になったそうです[1]

/// <summary>
/// にんげん
/// </summary>
/// <param name="FirstName">下の名前</param>
/// <param name="LastName">上の名前</param>
/// <param name="Age">年齢</param>
public record Person(string FirstName, string LastName, int Age);

// 以下は従来の記法
/// <summary>
/// にんげん
/// </summary>
public record Person
{
    public string FirstName { get; }
    public string LastName { get; }
    public int Age { get; }
    
    /// <summary>コンストラクタ</summary>
    /// <param name="FirstName">下の名前</param>
    /// <param name="LastName">上の名前</param>
    /// <param name="Age">年齢</param>
    public Person(string firstName, string lastName, int age)
        => (FirstName, LastName, Age) = (firstName, lastName, age);
}
脚注
  1. 私が16.9.1で試したところ、Intellisenseとしてはコンストラクタの引数はサポートされますがプロパティには効いていないようです ↩︎