Подтвердить что ты не робот

Почему `this` недоступен в инициализации Auto-Property С# 6.0?

У меня есть следующий класс кода:

public class Foo
{
    public Nested Bar { get; } = new Nested(this);

    public class Nested
    {
        public Nested(Foo foo)
        {
            foo.DoSomething();
        }
    }

    private void DoSomething()
    {

    }
}

Однако я получаю эту ошибку компиляции:

Ключевое слово 'this' недоступно в текущем контексте

Я могу исправить это, просто не используя Auto-Property Initializer и явно переместив его в конструктор:

public Nested Bar { get; }

public Foo()
{
    this.Bar = new Nested(this);
}

Почему так? Не инициализатор автоисторического значения фактически переведен в код конструктора в IL?

4b9b3361

Ответ 1

Просто: вы не можете использовать this в инициализаторах. Идея состоит в том, чтобы предотвратить утечку незавершенного объекта - Nested(this) может что-то сделать для вашего объекта, что приводит к очень запутывающим и трудным для понимания ошибкам. Имейте в виду, что инициализаторы выполняются перед любым добавленным конструктором. То же самое происходит и для инициализаторов полей точно так же:

private Nested _field = new Nested(this);

По сути, инициализаторы предназначены для выполнения простых инициализаций - исправления 98% -ной проблемы. Все, что связано с this, является более сложным, и вам нужно будет написать свой собственный конструктор - и взять на себя ответственность за любые проблемы времени:)

Ответ 2

Почему так? Не инициализатор автоисторического значения фактически переведен в код конструктора в IL?

Правила для автоматически реализованных инициализаторов свойств такие же, как и для инициализаторов полей по той же причине. Обратите внимание, что инициализаторы свойств выполняются перед телами базового класса, как и инициализаторы полей, поэтому вы все еще находитесь в контексте "несколько неинициализированного" объекта; больше, чем во время тела конструктора.

Итак, вы должны представить, что свойство преобразуется в это:

private readonly Nested bar = new Nested(this); // Invalid

public Nested Bar
{
    get { return bar; }
}

Короче говоря, это ограничение должно помешать вам попасть в неприятности. Если вам нужно ссылаться на this при инициализации свойства, просто сделайте это вручную в конструкторе согласно вашему второму примеру. (Это относительно редко по моему опыту.)