見出し画像

C# レコード型(record)をDictionaryのキーに使う

record型が導入された!

C# 9.0からrecord型が導入されましたので、その使い方の一例として、Dictionaryのキーとして使うことを本稿では考えてみます。

これまでは、Dictionaryのキーとしてプリミティブな型(stringとか)以外のものを使いたい場合は、classを実装して、GetHashCodeとEqualsをオーバーライドする必要がありました。

例えば、MyKeyクラスをDictionaryのキーとして使いたい場合は、以下のような実装が必要でした。

画像5

ここで、GetHashCodeを実装し忘れた場合Dictionaryのキーとして使うことはできません(Visual Studioのインテリジェンスは優秀なので、「GetHashCodeをオーバーライドし忘れていますよ」って教えてくれますが)。

これは、Dictionaryは効率化のためにHashCodeでもキーの等値性を判断しており、仮に同じように2つのオブジェクトをコンストラクトしても、その2つのオブジェクトのHashCodeは異なるためです。

以下はその一例です。

画像5

画像5

一方、GetHashCodeのみをオーバーライドして、Equalsをオーバーライドし忘れても、上記同様、意図通りの挙動ができません。。。ここら辺は一度自分で実験してみると良いかと思います。

GetHashCode、Equalsをオーバーライドする実装は、毎回(ほぼ)同じことを実装する必要があり、冗長でありますし、結構面倒だったりします。

もう少し楽に実装できないかな~と思っていたら、この度C# 9.0でrecord型がサポートされ、Equals、GetHashCodeの明示的なオーバーライドから解放されました!

record型とは

Microsoftの公式Docには以下のように記述されています。本稿では、特に「値の等価性」がうれしいということになります。

C#9 以降では、record キーワードを使用して、データをカプセル化するための組み込み機能を提供する参照型を定義します。 位置指定パラメーターまたは標準のプロパティ構文を使用して、不変のプロパティを持つレコード型を作成できます。
(中略)
レコードは変更可能ですが、これらは主に不変のデータ モデルをサポートすることを目的としています。 レコード型には次の機能があります。
・不変プロパティを持つ参照型を作成するための簡潔な構文
・データ中心の参照型に役立つ組み込みの動作:
  ・値の等価性
  ・非破壊的な変化の簡潔な構文
  ・表示用の組み込みの書式設定
・継承階層のサポート

record型を使ってみる

実際に先ほどのMyKeyをrecord型で実装してみると以下のようになります。

画像5

先ほどのclass型で定義したときよりもかなりすっきりと定義できます。record型の場合、同じようにコンストラクトした2つのオブジェクトは同一オブジェクトとみなされるため、目的のDictionaryのキーとして使えます。

画像5

ちなみに、record型はclass型同様に、位置指定パラメーターを使用して、不変のプロパティを持つレコード型を作成できますので、以下の実装は先ほどの標準のプロパティ構文を用いた場合と同じです。

画像6

画像7

もちろん、コンストラクタを実装することもできますし、structと異なり、継承することもできる点、柔軟性があります。


現場からは以上です。


この記事が気に入ったらサポートをしてみませんか?