Записи C # 9.0 — ненулевые ссылочные типы и конструктор

#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