2022年2月7日月曜日

C# 10.0 レコード型

どうも、もりもりです。

C# 10.0の便利な機能にレコードクラス(C# 9.0ですでに追加はされている)とレコード構造体があるのでメモ。

レコードクラス/レコード構造体

不変なプロパティを持つようなクラスや構造体を簡潔に書けます。 そして参照型でも値型のようにふるまってくれます。

名前と年齢のプロパティを持ったレコード型の宣言は下記のように書くだけ。

// レコードクラス
public record class PersonClass(string Name, int Age);
// レコード構造体
public record struct PersonStruct(string Name, int Age);

レコードクラスはpublic record PersonClassclassを省略して書いてもOK。

// レコードクラス
var person1 = new PersonClass(Name: "Taro", Age: 35);
Console.WriteLine($"person1: {person1}");

var person2 = new PersonClass(Name: "Hanako", Age: 35);
Console.WriteLine($"person2: {person2}");

Console.WriteLine($"person1 = person2 ? {person1 == person2}");

// レコード構造体
var person3 = new PersonStruct(Name: "Taro", Age: 35);
Console.WriteLine($"person3: {person3}");

var person4 = new PersonStruct(Name: "Hanako", Age: 35);
Console.WriteLine($"person4: {person4}");

Console.WriteLine($"person3 = person4 ? {person3 == person4}");

実行結果はこうなります。

> person1: PersonClass { Name = Taro, Age = 35 }
> person2: PersonClass { Name = Hanako, Age = 35 }
> person1 = person2 ? False
> person3: PersonStruct { Name = Taro, Age = 35 }
> person4: PersonStruct { Name = Hanako, Age = 35 }
> person3 = person4 ? False

また、ToString()でプロパティ名と値を表示してくれるのでこれも意外と便利なところ。 わざわざオーバーライドして書かなくて済むので。
このレコード型と同じようなクラスや構造体を自作しようと思うとEquals()やGetHashCode()をオーバーライドして書かないといけません。
さらにそのようなクラスを複数作ろうものなら。。。(って実際に作ることもあったのでマジで助かります!)

レコードクラスとレコード構造体の違い

違いは「クラスと構造体」の違いとほぼ同じだそうです。
構造体には継承はありませんので、EqualityContractプロパティは生成されないようです。
レコードクラスはimmutableですがレコード構造体はmutableなプロパティが生成されます。
immutableなレコード構造体を作りたい場合はreadonly record structとすればOK。

with式

with式を使うと元のインスタンスは書き換えずにクローンして一部のデータを書き換えることが可能です。

// レコードクラス
person2 = person1 with { Name = "Taro" };
Console.WriteLine($"person2: {person2}");

Console.WriteLine($"person1 = person2 ? {person1 == person2}");

// レコード構造体
person4 = person3 with { Name = "Taro" };
Console.WriteLine($"person4: {person4}");

Console.WriteLine($"person3 = person4 ? {person3 == person4}");
> person2: PersonClass { Name = Taro, Age = 35 }
> person1 = person2 ? True
> person4: PersonStruct { Name = Taro, Age = 35 }
> person3 = person4 ? True

データは書き換えずにクローンだけしたい場合はperson2 = person1 with { };とすればOK。

さいごに

今回は一部の機能しか紹介してませんが、他にも結構便利な機能は追加されてます。 .NET 6のLINQに追加されたMaxBy/MinByとかも地味に嬉しいですね。

業務上では新しい言語バージョンを使える環境はあまりないのですが、C#の更新は毎年楽しみにはしてます。 (次のC# 11.0の候補にはヘンなのも挙がってましたが。。。w) いかに簡潔に書けるかってやはり大事だと思うんですよね。書く人も読む人もイイことしかない。 なので開発環境を選べるのであれば常に最新の安定版を使用したいものです。

以上、もりもりでした。

0 件のコメント:

コメントを投稿