День 1391. #ЗаметкиНаПолях
Подробнее об Обязательных Членах Класса в C#11
В C#11 представлено новое ключевое слово required, которое может применяться к полю и свойству класса, записи или структуры.
class Foo {
internal required int _field;
internal required int
Prop { get; set; }
}
Оно обязывает вызывающий код инициализировать поле или свойство. Если этого не сделать:
var foo = new Foo();
мы получим ошибку CS9035: Required member 'Foo._field' must be set in the object initializer or attribute constructor. (Обязательный член 'Foo._field' должен быть задан в инициализаторе объекта или конструктор должен иметь атрибут.)
Это очень полезное дополнение для улучшения сценария инициализации объекта, особенно в отношении init-свойств, которые могут быть инициализированы только в конструкторе или в инициализаторе.
Ограничения обязательных членов
1. required не может применяться к закрытому члену, поскольку ограничение ключевого слова действует за пределами родительского класса, когда вызывающий объект создаёт его экземпляр.
2. required не может применяться к статическому члену, поскольку оно предназначено для использования только во время создания экземпляра объекта.
3. required не может применяться к члену, доступному только для чтения, который может быть назначен только в конструкторе.
Зачем это нужно?
Инициализаторы объектов были введены для преодоления некоторых известных ограничений конструктора, вроде необходимости соблюдать порядок параметров, необходимости задавать все параметры, даже которые не нужны, ломающих изменениях, когда в класс добавляется новый член и новый параметр в конструктор и т.п.
До сих пор было невозможно требовать, чтобы инициализаторы устанавливали член, что приводило к необходимости использовать конструктор в таком сценарии.
Обязательные члены и конструктор
Ключевое слово required на самом деле является частью публичного контракта всех конструкторов класса. Компилятор не пытается проверить, присваивается ли значение обязательному члену в самом конструкторе. Если это ваш случай, добавьте атрибут SetsRequiredMembers к конструктору, что сообщит компилятору, что обязательные члены заданы.
Обязательные члены и переопределение свойств
Есть несколько ограничений при переопределении обязательных свойств:
1. required нельзя использовать интерфейсах и для членов, являющихся явной реализацией интерфейса.
2. При переопределении обязательного виртуального или абстрактного свойства ключевое слово required должно быть указано повторно.
interface IInterface
{
int Prop { get; init; }
// ОШИБКА
required int Foo { get; init; }
}
abstract class Base
{
public required abstract int
Abstr { get; init; }
public required virtual int
Virt { get; init; }
}
class Derived : Base, IInterface
{
public int Foo { get; init; }
// ОШИБКА
required int IInterface.Prop { get; init; }
// required повторно в переопределениях
public required override int
Abstr { get; init; }
public required override int
Virt { get; init; }
}
Источник: https://blog.ndepend.com/c-11-required-members/