Итак избавились от точки в названии и получили записи.
Впервые попробовал. Поведение отличается от классов.
Взаимные ссылки типа parent <-> child дают переполнение стэка.
Я правда делал не честные записи, но менял ключевое слово clsss на record т.к. судя по документации особых различий не должно быть или я не заметил.
Стоит ли использовать записи в нынешнем виде или подождать до следующей LTS?
public abstract class BaseThing
{
public string Name { get; set; }
public override string ToString()
{
return $"[{this.GetType().Name}: Name={Name}]";
}
}
public record Person : BaseThing // <= error CS8864: Записи могут наследоваться только от объекта или другой записи. (Вот это особо удивило, class это не объект?)
{
private Item item;
public Item Item
{
get => item; set
{
item = value;
item.Person = this;
}
}
public override string ToString()
{
return base.ToString() + $"{Item}"; <= версия на классах работает, рекорд кидает переполнение стэка
}
}
public record Item : BaseThing
{
public Person Person { get; set; }
}
Здравствуйте, varenikAA, Вы писали:
AA>error CS8864: Записи могут наследоваться только от объекта или другой записи. (Вот это особо удивило, class это не объект?)
Здравствуйте, varenikAA, Вы писали:
AA>Итак избавились от точки в названии и получили записи.
Разве?
AA>Взаимные ссылки типа parent <-> child дают переполнение стэка.
Логично. На классах, если повторить поведение рекордов в ToString(), тоже свалится. Чтоб твой кейс не свалился, надо и у Item переопределить ToString(). ToString(), кстати, не наследует поведение базового рекорда.
Если в record хочется добавить вычисляемое get property, но надо закешировать результат в mutable field (больше некуда). Как этот field исключить из ToString, GetHashCode, Equals?
Если вручную переопределять все GetHashCode, Equals, ToString, то половина преимуществ record пропадает.
Может они сделали какой то attribute, для исключения? Логичнее было бы чтобы mutable fields вообще не включались в GetHashCode,.. Если надо, то добавить легче, чем убрать.
S_S>Если в record хочется добавить вычисляемое get property, но надо закешировать результат в mutable field (больше некуда). Как этот field исключить из ToString, GetHashCode, Equals? S_S>Если вручную переопределять все GetHashCode, Equals, ToString, то половина преимуществ record пропадает.
Хотя обходные пути есть — добавить это поле в производном record, а переопределения GetHashCode,.. направить на base.
Но плохо, что конструктор надо снова переопределять. Если был краткий primary конструктор, то много лишней писанины.
Лучше бы сделали, чтобы в производном record, в таких конструкторах неявно добавлялись параметры из base record.
public record Rec1(int Prop1)
{
}
public record Rec2(int Prop2) : Rec1 // Ошибка. В производном такие конструкторы нельзя. Если в базовом нет без параметров. Лучше бы неявно превращался в конструктор: Rec2(int Prop1, int Prop2)
{
}
Здравствуйте, Silver_S, Вы писали:
S_S>Если вручную переопределять все GetHashCode, Equals, ToString, то половина преимуществ record пропадает. S_S>Может они сделали какой то attribute, для исключения? Логичнее было бы чтобы mutable fields вообще не включались в GetHashCode,.. Если надо, то добавить легче, чем убрать.
Думаю, этот случай не для record. Но обычные классы то никуда не делись. Чтобы меньше писать, всегда можно использовать Fody или Source Generators.
Здравствуйте, Silver_S, Вы писали:
S_S>Чтобы не плодить темы, сюда вопрос.
S_S>Если в record хочется добавить вычисляемое get property, но надо закешировать результат в mutable field (больше некуда). Как этот field исключить из ToString, GetHashCode, Equals?
Потыкал щас. вообще это странно для записей изменять хэш. в этом же вся суть их.
Здравствуйте, VladD2, Вы писали:
VD>Надо понимать зачем они нужны. Тогда стоит. Я бы очень хотел их использовать, но у нас .net 4.0
Можно пример? Я вот только нашел их полезными для работы с System.Text.Json благодаря [attribute:property] удалось существенно уменьшить кол-во кода.
Внезапно осознал, что их нельзя использовать для UI т.к. все свойства init only, и следовательно можно вообще без св-в обойтись(использовать например структуры?).
Да и в связке с EF уже не так удобно. можно было бы автоклассы аналогично записям добавить.
В результате опять приходится писать кучу ручного кода.
Я вначале думал что это компилятор просто тупо генерит IEquitable, GetHashCode, Equals, ==, != и мутабельное клонирование. Все это есть в .NET Framework 2.0 и старше
Здравствуйте, varenikAA, Вы писали:
AA>Внезапно осознал, что их нельзя использовать для UI т.к. все свойства init only, и следовательно можно вообще без св-в обойтись(использовать например структуры?).
это в "коротком" синтаксисе они immutable. В полном для каждого поля ты задаеш видимость сеттера.
Здравствуйте, varenikAA, Вы писали:
VC>>это в "коротком" синтаксисе они immutable. В полном для каждого поля ты задаеш видимость сеттера.
AA>Таже портянка получится что и class?
Здравствуйте, VladCore, Вы писали:
VC>>>это в "коротком" синтаксисе они immutable. В полном для каждого поля ты задаеш видимость сеттера.
AA>>Таже портянка получится что и class?
VC>нет 🙃
Здравствуйте, varenikAA, Вы писали:
VC>>>>это в "коротком" синтаксисе они immutable. В полном для каждого поля ты задаеш видимость сеттера.
AA>>>Таже портянка получится что и class?
VC>>нет 🙃
AA>Например?
смотри внимательнее — я ответил на стартовое сообщение. А именно компилятор нагенерит IEquatable, GetHashCode, Equals, ==, !=
Здравствуйте, VladD2, Вы писали:
VD>Здравствуйте, varenikAA, Вы писали:
AA>>Стоит ли использовать записи в нынешнем виде или подождать до следующей LTS?
VD>Надо понимать зачем они нужны. Тогда стоит. Я бы очень хотел их использовать, но у нас .net 4.0
Компилятор то хотя бы не от 2010-й студии ?
В 2019-й студии или же просто с новым Rolsyn-ом собирается и работает отлично:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<LangVersion>9</LangVersion> <!-- Поддержка записей -->
<TargetFramework>net40</TargetFramework>
</PropertyGroup>
<ItemGroup>
<!-- Для 'System.Runtime.CompilerServices.IsExternalInit' . Можно и вручную добавить -->
<PackageReference Include="Theraot.Core" Version="3.2.5" />
</ItemGroup>
</Project>
using System;
namespace ConsoleApp22
{
public record A(int I, int J);
class Program
{
static void Main(string[] args)
{
var a = new A(1, 2);
var b = a with { I = 10 };
Console.WriteLine(a);
Console.WriteLine(b);
}
}
}
Здравствуйте, _NN_, Вы писали:
_NN>Компилятор то хотя бы не от 2010-й студии ?
2017-й
_NN>В 2019-й студии или же просто с новым Rolsyn-ом собирается и работает отлично:
С рослиновским компилятором тоже были проблемы какие-то. Сейчас ведется работа по переводу на новый корочный дотнет (наверно 5). За одно и компиляторы поднимем.
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.