Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Запись в C# — это класс или структуру , которая предоставляет специальный синтаксис и поведение для работы с моделями данных. Модификатор record
указывает компилятору синтезировать элементы, которые полезны для типов, основная роль которых хранит данные. Эти члены включают перегрузку ToString() и членов, поддерживающих равенство значений.
Когда следует использовать записи
Рекомендуется использовать запись вместо класса или структуры в следующих сценариях:
- Вы хотите определить модель данных, которая зависит от равенства значений.
- Необходимо определить тип, для которого объекты являются неизменяемыми.
Равенство значений
Для записей равенство значений означает, что две переменные типа записи равны, если типы совпадают, а все значения свойств и полей равны. Для других ссылочных типов, таких как классы, равенство означает равенство ссылок по умолчанию, если не реализовано равенство значений. То есть два переменных типа класса равны, если они ссылаются на один и тот же объект. Методы и операторы, определяющие равенство двух экземпляров записей, используют равенство значений.
Не все модели данных хорошо работают с равенством значений. Например, Entity Framework Core зависит от равенства ссылок, чтобы гарантировать использование только одного экземпляра типа сущности для концептуально одной сущности. По этой причине типы записей не подходят для использования в качестве типов сущностей в Entity Framework Core.
Неизменность
Неизменяемый тип — это такой тип, который предотвращает изменение значений свойств или полей объекта после его создания. Неизменяемость может быть полезной, когда требуется, чтобы тип был потокобезопасным или вы полагаетесь на то, что хэш-код останется неизменным в хэш-таблице. Записи предоставляют краткий синтаксис для создания и работы с неизменяемыми типами.
Неизменяемость не подходит для всех сценариев данных. Entity Framework Core, например, не поддерживает обновление с неизменяемыми типами сущностей.
Как записи отличаются от классов и структур
Тот же синтаксис, который объявляет и создает экземпляры классов или структур, может использоваться также и для записей. Просто замените ключевое слово class
record
или используйте record struct
вместо struct
. Аналогичным образом, тот же синтаксис для выражения связей наследования поддерживается классами записей. Записи отличаются от классов в следующих отношениях:
- Можно использовать позиционные параметры в первичном конструкторе для создания экземпляра типа с неизменяемыми свойствами.
- Те же методы и операторы, которые обозначают равенство или неравенство ссылок в классах (например, Object.Equals(Object) и
==
), обозначают равенство или неравенство в записях. - Выражение
with
можно использовать для создания копии неизменяемого объекта с новыми значениями в выбранных свойствах. - Метод
ToString
записи создает форматированную строку, которая показывает имя типа объекта и имена и значения всех его общедоступных свойств. - Запись может быть производной от другой записи. Запись не может наследоваться от класса, и класс не может наследоваться от записи.
Структуры записей отличаются от обычных структур тем, что компилятор автоматически синтезирует методы для определения равенства и ToString
. Компилятор синтезирует метод Deconstruct
для структур позиционной записи.
Компилятор синтезирует открытое свойство, допускающее только инициализацию, для каждого параметра первичного конструктора в record class
. В 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#.