Есть ли ссылка на частичное назначение объекта внутри синтаксиса инициализатора объекта в С# (Prop1 = {Prop2 = X})?

Учитывая следующие 2 класса (VS 2015 + .Net 4.5) с полностью изменяемыми свойствами:

class Wrapped
{
    public int A {get; set;}
    public int B {get; set;}
}

class Wrapper
{
    public int X {get; set;}
    public Wrapped Y  {get; set;}
    public Wrapper()
    {
       Y = new Wrapped  { A = 5, B = 10 };
    }
}

Я был заинтригован, обнаружив, что Resharper 8.x рекомендовал использовать синтаксис инициализатора объекта (UseObjectOrCollectionInitializer) в следующем сценарии вложенной инициализации, где я предполагал только частичное присвоение обернутого объекта — я хотел, чтобы остальные свойства экземпляра Wrapped должны сохранять любые значения по умолчанию, выданные конструктором класса Wrapper:

// My Original code
var demo1 = new Wrapper
{
    X = 5
};
demo1.Y.B = 23;

// Resharper's refactoring suggestion
var demo2 = new Wrapper
{
    X = 5,
    Y = { B = 23 }
};

Изначально я предполагал, что рефакторинг может быть синтаксическим сахаром для:

    new Wrapper
    {
        X = 5,
        Y = new Wrapped { B = 23 }
    };

Что, очевидно, не совпадает с моим кодом, так как он будет расточительно создавать и назначать свойство Y дважды (один раз в конструкторе по умолчанию Wrapper's и один раз в назначении Y, и, что еще хуже, в установщике он потеряет все другие значения свойств, назначенные конструктором Wrapper's, так как он примет любые значения, назначенные конструктором Wrapped.

Однако после дизассемблирования IL с помощью LinqPad я был поражен правильностью Resharper, а именно тем, что синтаксис инициализатора:

Y = { B = 23 }

эквивалентно явному

demo1.Y.B = 23;

Итак, мой вопрос: есть ли официальная ссылка на этот "частичный" (т.е. нереконструированный) синтаксис присваивания в синтаксисе инициализации объекта. Мне не удалось легко найти его в MSDN, например. Инициализаторы объектов и коллекций, так что я могу взвесить относительные преимущества и опасности этого синтаксиса?

Изменить

Кроме того, отмечено, что, как и в случае с явным синтаксисом,

Y = { B = 23 }

Будет выброшено NullReferenceException, если B не создан внутри конструктора Y.

Разборка ИЖ:

то есть оба demo1 и demo2 приводят к этому IL:

Wrapper..ctor
Wrapper.set_X
Wrapper.get_Y
Wrapped.set_B

В то время как demo3 приводит к неправильному

Wrapper..ctor
Wrapper.set_X
Wrapped..ctor
Wrapped.set_B
Wrapper.set_Y

Я разместил небольшой образец, показывающий различия между 1 и 2 и 3, на IdeOne здесь


person StuartLC    schedule 02.11.2015    source источник
comment
Я думаю, что нашел обман с подходящим ответом (ссылкой на главу в спецификации С#). Если нет, смело открывайте снова.   -  person Lucas Trzesniewski    schedule 02.11.2015
comment
@LucasTrzesniewski Спасибо - нашел - ссылка на инициализатор вложенных объектов 7.6.10.2. Виноват.   -  person StuartLC    schedule 02.11.2015