C#におけるレコード型とオブジェクトの等価性

2024年9月8日

C# 9.0で導入されたレコード型(record)は、特に不変性(イミュータブル性)を持つデータ構造として設計されています。レコード型は、クラス型と比較して、オブジェクトの等価性に関して重要な違いがあります。この資料では、レコード型における等価性の扱い方について説明し、==演算子やReferenceEqualsメソッドとの関係を中心に解説します。

レコード型と値の等価性

サンプルコード

以下は、レコード型を使用してBook型を定義し、2つの異なるインスタンスが値として等価かどうかを確認するコード例です。

public record Book(string Title);

internal class Program
{
    private static void Main(string[] args)
    {
        // 2つの異なるBookオブジェクトを作成
        Book book1 = new Book("同じタイトル");
        Book book2 = new Book("同じタイトル");

        // ==演算子で比較
        Console.WriteLine("book1とbook2は同じですか? " + (book1 == book2)); // True
    }
}

結果

このコードを実行すると、以下の出力が得られます。

book1とbook2は同じですか? True

解説

  • 値の等価性: レコード型では、デフォルトで「値の等価性」がサポートされています。これは、プロパティの値が同じであれば、オブジェクトが異なるインスタンスであっても==演算子で比較した際にTrueを返すことを意味します。
  • ==演算子の動作: レコード型では、==演算子が自動的にオーバーロードされ、プロパティの値を比較するようになっています。このため、book1book2は異なるインスタンスですが、同じタイトルを持つため、等価と見なされます。

レコード型と参照の等価性

レコード型でも、必要に応じてオブジェクトの参照が同一であるかを確認することができます。これには、ReferenceEqualsメソッドを使用します。

サンプルコード

public record Book(string Title);

internal class Program
{
    private static void Main(string[] args)
    {
        Book book1 = new Book("同じタイトル");
        Book book2 = new Book("同じタイトル");
        Book book3 = book1;

        Console.WriteLine("book1とbook2は同じ参照ですか? " + ReferenceEquals(book1, book2)); // False
        Console.WriteLine("book1とbook3は同じ参照ですか? " + ReferenceEquals(book1, book3)); // True
    }
}

結果

このコードを実行すると、以下の出力が得られます。

book1とbook2は同じ参照ですか? False
book1とbook3は同じ参照ですか? True

解説

  • 参照の等価性ReferenceEqualsメソッドは、2つのオブジェクトが同じメモリ位置を参照しているかどうかを確認します。book1book2は異なるインスタンスなので、Falseを返しますが、book3book1と同じインスタンスを参照しているため、Trueを返します。

レコード型の利点

自動生成されるメンバー

レコード型では、デフォルトで以下のメンバーが自動的に生成されます。

  • == 演算子
  • Equals メソッド
  • GetHashCode メソッド

これにより、オブジェクトの等価性のチェックやハッシュコードの生成が簡単になります。

簡潔さと不変性

  • 簡潔さ: レコード型を使用することで、クラス型で必要だった等価性チェックのコードが自動生成され、コードが簡潔になります。
  • 不変性: レコード型は通常、イミュータブル(不変)なデータを扱う際に使用されます。プロパティはデフォルトで読み取り専用となります。

まとめ

レコード型は、C#においてオブジェクトの等価性を扱う上で非常に便利な機能を提供します。値の等価性をサポートし、データ構造の比較を簡潔かつ正確に行うことができるため、特に不変のデータ構造を扱うシナリオに適しています。==演算子とReferenceEqualsメソッドの使い分けを理解することで、より意図的で明確なコードを書くことができるでしょう。


この資料は、レコード型とオブジェクトの等価性に関する基本的な理解を深めることを目的としています。

C#

Posted by hidepon