#c# #c#-9.0
#c# #c #-9.0
Вопрос:
Я попробовал всего лишь простую запись:
#nullable enable
public record Product
{
public readonly string Name;
public readonly int CategoryId;
public readonly string Phone;
public readonly Address Address;
public readonly Manager Manager;
}
Я получаю предупреждения:
Ненулевое свойство ‘Name’ неинициализировано. Рассмотрите возможность объявления свойства как обнуляемого.
(то же самое для всех полей, кроме CategoryID)
В принципе, если я правильно понимаю, конструктор, принимающий и устанавливающий все поля, не автоматически генерируется компилятором и (при использовании #nullable enable
) Я должен написать это сам, т. Е.:
public Product(string Name, int CategoryId, string Phone, Address Address, Manager Manager) {
this.Name=Name;
this.CategoryId=CategoryId;
...
}
Мой вопрос в том, правильно ли это? Я очень удивлен этим, поскольку думал, что весь смысл в том, чтобы сделать создание подобных записей действительно простым, а необходимость писать / поддерживать конструктор очень утомительна, особенно для больших записей, которые часто меняются.
Или я что-то здесь упускаю?
Комментарии:
1. Почему вы не объявляете их должным образом как
init
свойства вместо общедоступных полей, доступных только для чтения?2. Поскольку вы создаете эти свойства
readonly
, вы должны их инициализировать. И компилятор волшебным образом не знает, как вы хотите, чтобы это было сделано.3. @CamiloTerevinto использование свойств инициализации не изменяет предупреждения,
4. @juergend удаление только для чтения не меняет предупреждение
5. Я думаю, вам не нужно вручную генерировать ctor (но я могу ошибаться), но даже в этом случае вы все равно можете использовать
new Product()
, так что вы все равно можете получить неинициализированные элементы. По крайней мере, для версии 9.0 вы должны продолжить писать ctors, если хотите#nullable enable
Ответ №1:
Кажется, вы ожидаете автоматически сгенерированного основного конструктора, но он автоматически генерируется (и в целом вы получаете все преимущества записи) при использовании параметров записи в объявлении типа записи, которые автоматически сопоставляются с общедоступными get
и init
свойствами и автоматически инициализируются из основного конструктора, что устраняет предупреждение NRT.
Это означает, что вы получаете весь набор типов записей, в основном используя обычный синтаксис конструктора с добавленным record
ключевым словом:
public record Product(string Name, int CategoryId, string Phone, Address Address, Manager Manager) { }
Комментарии:
1. Я вижу, если я попробую это — увидите sharplab.io/#gist:830bc1e956d87308c739e9b943aeef1a — свойства
{ get; set; }
не{ get; init; }
имеют2. Ну, то, что я написал под «спецификацией». И то, что мы на самом деле получаем, — это текущая реализация «предварительного просмотра». Вот почему в целом я против тестирования / обсуждения предварительных просмотров, поскольку они могут быть далеки от того, что мы получим с выпуском. Вся идея типов записей заключается в том, чтобы сделать их типизированным вариантом анонимных типов. По-видимому, над ними предстоит еще поработать 🙂
3. Но я пробовал это в последнем предварительном просмотре VS2019, и хотя object browser отображает их как
get; set;
, компилятор не позволяет устанавливать их извне, поэтому, возможно, просто отсутствуютinit
метаданные.4. Для тех, кому интересно, что означает » Основной конструктор «, вот объяснение — infoq.com/news/2020/01/CSharp-Primary-Constructors