В чем разница между Init-Only и ReadOnly в C# 9?
Я просматриваю новые функции C# 9, которые скоро будут выпущены. Вместе с ним вводятся свойства только для инициализации.
Одно большое ограничение сегодня заключается в том, что свойства должны быть изменяемыми, чтобы инициализаторы объектов работали: они работают, сначала вызывая конструктор объекта (в данном случае по умолчанию, без параметров), а затем присваивая значения установщикам свойств.
Свойства только для инициализации исправляют это! Они вводят метод доступа init, который является вариантом метода доступа set, который может быть вызван только во время инициализации объекта:
public class Person
{
public string FirstName { get; init; }
public string LastName { get; init; }
}
С этим объявлением приведенный выше клиентский код остается допустимым, но любое последующее присвоение свойствам FirstName и LastName является ошибкой. Что означает эта линия? Если ReadOnly также делает то же самое, тогда каково использование свойства Init-Only.
4 ответа
Как указано в сообщении о новых возможностях C# 9 ,
Одно большое ограничение сегодня заключается в том, что свойства должны быть изменяемыми, чтобы инициализаторы объектов работали: они работают, сначала вызывая конструктор объекта (в данном случае по умолчанию, без параметров), а затем присваивая значения установщикам свойств.
Однако типы значений с модификаторами readonly неизменяемы, как указано в документации только для чтения.
Следовательно, нельзя использовать свойства только для чтения с инициализаторами объектов.
Однако со свойствами только для инициализации вы можете использовать инициализаторы объектов.
Назначение свойств только для Init- разрешить назначение только в инициализаторе объекта или конструкторе для вашего класса.
Если мы рассмотрим ваш
Person
класс, отнесение к
FirstName
или же
LastName
разрешено в конструкторе или в инициализаторе объекта, но вы не можете назначить
FirstName
или же
LastName
не сработает:
public class Person
{
public string FirstName { get; init; }
public string LastName { get; init; }
// this is a constructor
public Person()
{
this.FirstName = "first name"; // works
this.LastName = "last name"; // works
}
}
//this is a random method
public SomeMethod()
{
Person myPerson = new Person
{
FirstName = "first name", // works
LastName = "last name" // works
};
myPerson.FirstName = "change the first name"; // Error (CS8852)
myPerson.LastName = "change the last name"; // Error (CS8852)
}
Это также предотвращает раздувание конструкторов с большим количеством необязательных параметров. Например, в следующем классе:
public class InitOnlyExample
{
private readonly string _firstName;
private readonly string _lastName;
private readonly string _address;
private readonly int _zipCode;
private readonly string _phoneNumber;
public InitOnlyExample(
string firstName,
string lastName,
string address,
int zipCode = default,
string phoneNumber = default
)
{
_firstName = firstName;
_lastName = lastName;
_address = address;
_zipCode = zipCode;
_phoneNumber = phoneNumber;
}
public string FirstName { get { return _firstName; } }
public string LastName { get { return _lastName; } }
public string Address { get { return _address; } }
public int ZipCode { get { return _zipCode; } }
public string PhoneNumber { get { return _phoneNumber; } }
}
В отличие от set свойство только для инициализации может быть установлено только в конструкторе или с помощью инициализатора свойства.