レコードの概要

レコードとは、データ モデルを操作するための特殊な構文と動作を提供するクラスです。 クラスの詳細については、クラスに関するページを参照してください。

レコードを使用する場面

次のシナリオでは、クラスの代わりにレコードを使用することを検討してください。

  • 値の等価性に依存するデータ モデルを定義する。
  • オブジェクトが不変となる参照型を定義する。

値の等価性

レコードにおける値の等価性とは、型が一致し、かつプロパティおよびフィールドの値がすべて一致する場合にレコード型の 2 つの変数が等しいことを意味します。 クラスなどの他の参照型における等価性とは、参照の等価性を意味します。 つまり、クラス型の 2 つの変数は、同じオブジェクトを参照する場合、等しいことになります。 2 つのレコード インスタンスが等しいかどうかを判断するメソッドと演算子では、値の等価性が使用されます。

すべてのデータ モデルが値の等価性に適しているわけではありません。 たとえば、Entity Framework Core では、概念的に 1 つのエンティティであるものに対して、エンティティ型の 1 つのインスタンスだけが確実に使用されるようにするために、参照の等価性に依存します。 このため、レコード型は Entity Framework Core でエンティティ型として使用するのに適していません。

不変性

不変型とは、オブジェクトがインスタンス化された後にそのプロパティまたはフィールドの値を変更できないようにするためのものです。 不変性は、型をスレッドセーフにする必要がある場合またはハッシュ テーブル内で変化のないハッシュ コードに依存している場合に役立ちます。 レコードには、不変型を作成および操作するための簡潔な構文が用意されています。

不変性は、すべてのデータ シナリオに適しているわけではありません。 たとえば、Entity Framework Core では、不変のエンティティ型を使用した更新がサポートされていません。

レコードとクラスの相違点

クラスを宣言およびインスタンス化するのと同じ構文がレコードでも使用できます。 キーワード class をキーワード record に置き換えるだけです。 同様に、継承関係を表す場合も同じ構文がレコードによってサポートされています。 レコードは次の点がクラスとは異なります。

  • 位置指定パラメーターを使用して、不変プロパティを持つ型を作成してインスタンス化することができます。
  • クラスで参照の等価性または非等価性を示すメソッドと演算子 (Object.Equals(Object)== など) は、レコードでは値の等価性または非等価性を示します。
  • withを使用すれば、選択したプロパティに新しい値を指定して、不変オブジェクトのコピーを作成することができます。
  • レコードの ToString メソッドを使用すると、オブジェクトの型名とそのすべてのパブリック プロパティの名前および値を示す書式設定された文字列が作成されます。
  • レコードは、別のレコードから継承できます。 レコードはクラスから継承できません。また、クラスはレコードから継承できません。

次の例では、位置指定パラメーターを使用してレコードを宣言およびインスタンス化するパブリック レコードを定義します。 次に、型名とプロパティ値を出力します。

public record Person(string FirstName, string LastName);

public static void Main()
{
    Person person = new("Nancy", "Davolio");
    Console.WriteLine(person);
    // output: Person { FirstName = Nancy, LastName = Davolio }
}

次の例では、レコードでの値の等価性を示します。

public record Person(string FirstName, string LastName, string[] PhoneNumbers);

public static void Main()
{
    var phoneNumbers = new string[2];
    Person person1 = new("Nancy", "Davolio", phoneNumbers);
    Person person2 = new("Nancy", "Davolio", phoneNumbers);
    Console.WriteLine(person1 == person2); // output: True

    person1.PhoneNumbers[0] = "555-1234";
    Console.WriteLine(person1 == person2); // output: True

    Console.WriteLine(ReferenceEquals(person1, person2)); // output: False
}

次の例では、with 式を使用して、不変オブジェクトをコピーし、プロパティの 1 つを変更する方法を示します。

public record Person(string FirstName, string LastName)
{
    public string[] PhoneNumbers { get; init; }
}

public static void Main()
{
    Person person1 = new("Nancy", "Davolio") { PhoneNumbers = new string[1] };
    Console.WriteLine(person1);
    // output: Person { FirstName = Nancy, LastName = Davolio, PhoneNumbers = System.String[] }

    Person person2 = person1 with { FirstName = "John" };
    Console.WriteLine(person2);
    // output: Person { FirstName = John, LastName = Davolio, PhoneNumbers = System.String[] }
    Console.WriteLine(person1 == person2); // output: False

    person2 = person1 with { PhoneNumbers = new string[1] };
    Console.WriteLine(person2);
    // output: Person { FirstName = Nancy, LastName = Davolio, PhoneNumbers = System.String[] }
    Console.WriteLine(person1 == person2); // output: False

    person2 = person1 with { };
    Console.WriteLine(person1 == person2); // output: True
}

詳細については、「レコード (C# リファレンス)」を参照してください。

C# 言語仕様

詳細については、「C# 言語の仕様」を参照してください。 言語仕様は、C# の構文と使用法に関する信頼性のある情報源です。