День 1371. #ЗаметкиНаПолях
Записи с Выражениями и Вычисляемыми Свойствами
Учитывая краткость записей и даже игнорируя другие их характеристики, когда нужен неизменяемый тип, проще всего использовать запись. Однако стоит помнить об их характеристиках, чтобы не получить неожиданные результаты.
Рассмотрим следующую запись:
public record SomeRecord(string Val)
{
public string CalcVal { get; } =
Val + " *calculated*";
}
Мы используем первичный конструктор для объявления и инициализации свойства Val, но у нас также есть другое свойство CalcVal, которое вычисляется с использованием Val. Вроде просто. Но что если мы используем with для создания другой записи:
var x = new SomeRecord("42");
var y = x with {Val = "69"};
Console.WriteLine(x);
Console.WriteLine(y);
Вот что получилось:
SomeRecord { Val = 42, CalcVal = 42 *calculated* }
SomeRecord { Val = 69, CalcVal = 42 *calculated* }
CalcVal во второй записи по-прежнему имеет то же значение, что и в первой. Это имеет смысл, так как при использовании выражения with запись клонируется, а новые значения получают только свойства, указанные в скобках.
Простой способ исправить это — использовать вычисляемое свойство:
public record SomeRecord(string Val)
{
public string CalcVal => Val + " *calculated*";
}
Это решает проблему и может быть допустимым решением в целом. Однако каждый раз, когда мы вызываем CalcVal значение будет вычисляться заново. В зависимости от того, как используется свойство, это может быть, а может и не быть проблемой, поскольку мы всегда повторяем одну и ту же логику и создаем новые объекты для возврата значения.
Источник: https://blog.codingmilitia.com/2022/09/01/beware-of-records-with-expressions-and-calculated-properties/