C# の レコード は、データ モデルを操作するための特別な構文と動作を提供する クラスの または 構造体 です。
record
修飾子は、データを格納する主な役割を持つ型に役立つメンバーを合成するようにコンパイラに指示します。 これらのメンバーには、ToString() のオーバーロードと、値の等価性をサポートするメンバーが含まれます。
レコードを使用するタイミング
次のシナリオでは、クラスまたは構造体の代わりにレコードを使用することを検討してください。
- 値の等価性に依存するデータ モデル定義する必要があります。
- オブジェクトが変更できない型を定義する必要があります。
値の等価性
レコードの場合、値の等価性は、型が一致し、すべてのプロパティ値とフィールド値が等しい場合に、レコード型の 2 つの変数が等しいことを意味します。 クラスなどの他の参照型の場合、等値 は、値の等価性 が実装されていない限り、既定で等値 参照を意味します。 つまり、クラス型の 2 つの変数は、同じオブジェクトを参照する場合は等しくなります。 2 つのレコード インスタンスの等価性を決定するメソッドと演算子は、値の等価性を使用します。
すべてのデータ モデルが値の等価性で適切に機能するわけではありません。 たとえば、Entity Framework Core は、概念的に 1 つのエンティティに対してエンティティ型のインスタンスを 1 つだけ使用するように、参照の等価性に依存します。 このため、レコード型は Entity Framework Core でエンティティ型として使用する場合には適していません。
不変
変更できない型は、インスタンス化された後にオブジェクトのプロパティまたはフィールド値を変更できないようにするものです。 不変性は、型をスレッド セーフにする必要がある場合や、ハッシュ テーブル内で同じままのハッシュ コードに依存している場合に便利です。 レコードは、変更できない型を作成および操作するための簡潔な構文を提供します。
不変性は、すべてのデータ シナリオに適しているわけではありません。 たとえば、Entity Framework Core は、変更できないエンティティ型での更新をサポートしていません。
レコードと、クラスおよび構造体との違い
クラスまたは構造体を宣言およびインスタンス化するのと同じ構文をレコードでも使用できます。
class
キーワードを record
に置き換えるか、record struct
の代わりに struct
を使用してください。 同様に、継承リレーションシップを表すのと同じ構文がレコード クラスでサポートされます。 レコードは、次の点でクラスとは異なります。
- プライマリ コンストラクター で 位置指定パラメーターを使用して、変更できないプロパティを持つ型を作成およびインスタンス化できます。
- クラス内の参照の等価性または不等値 (Object.Equals(Object) や
==
など) を示すのと同じメソッドと演算子は、レコード内の 値の等価性または不等値 を示します。 -
with
式 を使用して、選択したプロパティに新しい値を含む変更できないオブジェクトのコピーを作成できます。 - レコードの
ToString
メソッドは、オブジェクトの型名とそのすべてのパブリック プロパティの名前と値を示す書式設定された文字列を作成します。 - レコードは別のレコード からを継承することができる。 レコードはクラスから継承できません。また、クラスはレコードから継承できません。
レコード構造体は、コンパイラによって同等のメソッドおよび ToString
が合成されるという点で構造体とは異なります。 コンパイラは、位置指定レコード構造体の Deconstruct
メソッドを合成します。
コンパイラは、record class
内の各プライマリ コンストラクター パラメーターのパブリック init 専用プロパティを合成します。
record struct
では、コンパイラはパブリック読み取り/書き込みプロパティを合成します。 コンパイラは、修飾子を含まない class
型と struct
型のプライマリ コンストラクター パラメーターのプロパティ record
作成しません。
使用例
次の例では、位置指定パラメーターを使用してレコードを宣言およびインスタンス化するパブリック レコードを定義します。 その後、型名とプロパティ値が出力されます。
public record Person(string FirstName, string LastName);
public static class Program
{
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 class Program
{
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
式を使用して変更できないオブジェクトをコピーし、いずれかのプロパティを変更する方法を示します。
public record Person(string FirstName, string LastName)
{
public required string[] PhoneNumbers { get; init; }
}
public class Program
{
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# の構文と使用法の決定的なソースです。
.NET