primary constructors (первичные конструкторы класс/структур), то я почему-то думал, что параметры данного сахара разворачиваются в приватные ридонли поля, для обеспечения иммутабельности. Однако по какой-то причине авторы ушли в другую сторону, и это теперь даже не поля))Да, в ранних версиях предложения первичного конструктора, он должен был работать так же, как в record типах, но генерирующим приватные поля вместо открытого свойства. Однако во время разработки команда C# решила изменить поведение. И имеем следующее, что параметры первичного конструктора — это просто переменные, как в обычном конструкторе, но они оказываются в области видимости всего типа. То есть по факту данные параметры не влияют на состояние объекта и мы не можем, например, обратиться к ним через
this, это просто не скомпилируется.И вроде бы кажется, что область видимости приватная и все должно быть нормально, т.к. ни один здравомыслящий разработчик не будет брать и переопределять эти первичные параметры... Но, зная, какие кадры бывают на проектах и как они это все могут разломать, то я бы не надеялся. И тут есть несколько вариантов перестраховаться.
Самый простой - запрет на использование
primary constructor. И за это можно получить кучу навоза в лицо от коллег, которые будут отстаивать, что все безопасно и все пишут хороший код.Второй вариант - явное создание
readonly полей с такими же наименованиями, что и у параметров первичного конструктора. В таком случае параметры перекроются и не будут больше доступны после присвоения полям.😡 Плохо
public class GetRequestQuery(
ReadOnlyContext context,
IEquipmentService equipmentService)
{
// ...
}
👍 Хорошо
public class GetRequestQuery(
ReadOnlyContext _context,
IEquipmentService _equipmentService)
{
private readonly ReadOnlyContext _context = _context;
private readonly IEquipmentService _equipmentService = _equipmentService;
// ...
}
👍 И есть еще один интересный инструмент на сорс генераторах, который мне посоветовал товарищ СтепВан. Он позволяет нам написать все необходимые
readonly поля, и с ними будет сгенерирован коснтруктор. Выглядит весьма прикольно, но с колегами говном покидаться все равно придется.[PrimaryConstructor]
public partial class GetRequestQuery
{
private readonly ReadOnlyContext _context;
private readonly IEquipmentService _equipmentService;
// ...
}