Статья опубликована в рамках: LXIV Международной научно-практической конференции «Экспериментальные и теоретические исследования в современной науке» (Россия, г. Новосибирск, 26 апреля 2021 г.)
Наука: Технические науки
Скачать книгу(-и): Сборник статей конференции
дипломов
ВВЕДЕНИЕ В ТИПЫ ЗАПИСИ В C # 9
INTRO TO RECORD TYPES IN C# 9
Aghasi Seyranyan
student, National Polytechnic University of Armenia,
Armenia, Erevan
АННОТАЦИЯ
В заключение хочу сказать , что эта функция может значительно снизить шум шаблонов и кода в вашем проекте. Использование объектов-значений настолько распространено, что эта функция сразу становится фаворитом для любого большого проекта. Я надеюсь, что вы сможете начать включать записи в свою кодовую базу, это фантастическая функция.
ABSTRACT
In conclusion, this feature can drastically reduce boilerplate and code noise in your project. The use of value objects is such a common use-case, that this feature becomes an immediate favorite for any large project. I hope you can start incorporating records into your codebase, it's a fantastic feature.
В недавнем выпуске .NET 5 и C # 9 в язык C # были добавлены некоторые замечательные новые функции. Пожалуй, наиболее заметным дополнением являются типы записей. В этой статье я объясню эту функцию и почему мы можем ее использовать.
POCOs, также известные как обычные старые объекты C #
В большинстве приложений, которые мы пишем, мы часто имеем дело с объектами, которые не инкапсулируют какое-либо состояние или поведение. Эти объекты обычно представляют собой просто набор свойств, которые мы можем использовать для сериализации / десериализации данных JSON или для работы с операциями с базой данных. Возможно, вы слышали, что эти типы объектов называются POCO или POJO для "Plain-old C# objects" и "Plain-old Java objects" соответственно. Это очень распространенный шаблон, используемый в производственном программном обеспечении, но есть довольно много шаблонов, которые поставляются с этими типами объектов. Мы все видели этот тип кода. Вот пример:
- public class Employee
- {
- public string FirstName { get; set; }
- public string LastName { get; set; }
- public string EmployeeId { get; set; }
- }
Часто мы хотим рассматривать эти «глупые объекты» как типы значений. Одна вещь, которую обычно делают с типами значений, - это проверка равенства. Когда мы сравниваем два объекта C # с помощью == , мы проверяем ссылочное равенство. Другими словами, мы сравниваем адреса памяти этих объектов. Вместо этого мы можем сравнить эти объекты по значению, поскольку мы рассматриваем эти объекты как набор значений, а не как память в куче. Мы можем добавить в наш класс возможность проверки структурного равенства, просто добавив еще несколько шаблонов:
- public class Employee : IEquatable<Employee>
- {
- public string FirstName { get; set; }
- public string LastName { get; set; }
- public string EmployeeId { get; set; }
- public bool Equals(Employee other)
- {
- if (Object.ReferenceEquals(other, null))
- {
- return false;
- }
- if (Object.ReferenceEquals(this, other))
- {
- return true;
- }
- if (this.GetType() != other.GetType())
- {
- return false;
- }
- return (FirstName == other.FirstName) && (LastName == other.LastName) && (EmployeeId == other.EmployeeId);
- }
- public override bool Equals(object obj)
- {
- return Equals(obj as Employee);
- }
- public static bool operator ==(Employee lhs, Employee rhs)
- {
- if (Object.ReferenceEquals(lhs, null))
- {
- if (Object.ReferenceEquals(rhs, null))
- {
- return true;
- }
- return false;
- }
- return lhs.Equals(rhs);
- }
- public static bool operator !=(Employee lhs, Employee rhs)
- {
- return !(lhs == rhs);
- }
- public override int GetHashCode()
- {
- return HashCode.Combine(FirstName, LastName, EmployeeId);
- }
- }
Посмотрите, как быстро взорвался этот простой класс только потому, что мы хотим сравнивать по значению, а не по ссылке. Что еще хуже, если мы хотим добавить еще одно свойство к классу Employee, мы должны убедиться, что мы обновили реализацию Equals () для компенсации. Таким образом, мы не только резко увеличили шум в нашем коде, но и создали среду, в которой ошибки будут жить позже. При работе с этими объектами значений очень удобно иметь возможность деструктурировать свойства объекта в локальные переменные. В C # эта функция называется деконструкцией (на других языках она называется деструктуризацией ). Пример деконструкции:
1. var (firstname, lastname, employeeId) = myEmployee;
В этом надуманном примере у нас есть объект Employee с именем myEmployee, и мы деструктурируем свойства в локальные переменные. Давайте добавим эту функциональность в наш класс Employee:
- public void Deconstruct(out string firstName, out string lastName, out string employeeId)
- {
- firstName = FirstName;
- lastName = LastName;
- employeeId = EmployeeId;
- }
Когда этот шаблон добавлен в наш класс, мы можем выполнить описанную ранее деструктуризацию.
Решение для всего этого шаблона: типы записей
Если вы когда-либо использовали Kotlin раньше, возможно, вы знаете о фантастической функции, известной как класс данных. Цель такой функции, как класс данных, - решить проблему шаблонов, с которой мы здесь сталкиваемся. Нам нужен простой набор свойств, которые мы можем передавать по слоям нашего приложения, но нам также нужна встроенная функциональность, которую мы ожидаем от использования типа значения.
А вот тот же класс, использующий новую функцию типов записи C # 9:
1. record Employee(string FirstName, string LastName, string EmployeeId);
Неизменяемость и типы записей
Теперь следует отметить, что между двумя реализациями есть ключевое различие. В версии записи типа Employee эти общедоступные свойства полностью неизменяемы. Если вы попытаетесь изменить свойство, вы получите следующую ошибку:
Эта неизменность глубокая, а не поверхностная. Если у нас есть ссылочный тип как свойство в записи Employee, он все равно будет выдавать эту ошибку при попытке изменить ссылочный тип. Вместо того, чтобы изменять свойства этой записи напрямую, мы можем вместо этого создать копию объекта, но с нашими новыми желаемыми значениями. Это делается с помощью нового с синтаксисом , который идет вместе с типами записей.
- var employee1 = new Employee("Sean", "Franklin", "555");
- var employee2 = employee1 with { FirstName = "Bob" };
Используя ключевое слово вместе со списком инициализаторов, мы получаем новый объект Employee, которому присвоено новое значение. Если вам действительно нужна изменчивость в вашем POCO, то это можно включить, определив явно общедоступные свойства в записи.
- record Employee(string FirstName, string LastName, string EmployeeId)
- {
- public string FirstName { get; set; } = FirstName;
- public string LastName { get; set; } = LastName;
- public string EmployeeId { get; set; } = EmployeeId;
- }
Список литературы:
- What's new in C# 9.0 [Электронный ресурс]. – Режим доступа: https://docs.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-9 (дата обращения: 17.04.21)
- Welcome to C# 9.0 [Электронный ресурс]. – Режим доступа: https://devblogs.microsoft.com/dotnet/welcome-to-c-9-0/ (дата обращения: 17.04.21)
дипломов
Оставить комментарий