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

Почему этот инициализатор инициализации вложенных объектов генерирует исключение нулевой ссылки?

Следующий тестовый сценарий генерирует исключение с помощью NULL-ссылки, когда он пытается назначить Id объекту, который является нулевым, поскольку в коде отсутствует "новое R" перед инициализатором объекта.

Почему это не поймано компилятором? Почему это разрешено, в каких случаях это будет значимой конструкцией?

[TestClass]
public class ThrowAway
{
    public class H
    {
        public int Id { get; set; }
    }

    public class R
    {
        public H Header { get; set; }
    }

    [TestMethod]
    public void ThrowsException()
    {
        var request = new R
                      {
                          Header =
                          {
                              Id = 1
                          },
                      };
    }
}
4b9b3361

Ответ 1

Компилятор не дает предупреждения, потому что у вас может быть:

public class R
{
    public H Header { get; set; }

    public R()
    {
        Header = new H();
    }
}

поэтому Header может быть инициализирован кем-то/чем-то. Решение, если кто-то/что-то инициализирует Header, является сложной проблемой (вероятно, подобной проблеме Halting)... Не то, что компилятор хочет решить для вас: -)

Из спецификаций С#:

Инициализатор элемента, который указывает инициализатор объекта после знака равенства, является инициализатором вложенного объекта, то есть инициализацией внедренного объекта. Вместо назначения нового значения полю или свойства назначения в инициализаторе вложенных объектов рассматриваются как назначения членам поля или свойства. Инициализаторы вложенных объектов не могут применяться к свойствам с типом значения или к полям только для чтения со значением типа.

Мы находимся в случае вложенного инициализатора и видим выделенную часть. Я этого не знал.

Теперь обратите внимание, что new R { } - с помощью С# spec, a 7.6.10.1 Object creation expressions, за которым следует object-initializer, а Header = { } - "чистый" 7.6.10.2 Object initializers.