是否有参考"部分对象分配"在C#中的对象初始化程序语法内部(Prop1 = {Prop2 = X})?

时间:2015-11-02 14:54:05

标签: c# constructor object-initializers

鉴于以下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构造函数分配的任何其他属性值的setter,因为它将假设Wrapped的构造函数指定的任何值。

然而,在使用LinqPad进行IL反汇编时,我很惊讶Resharper是正确的,即初始化语法:

Y = { B = 23 }

相当于一个明确的

demo1.Y.B = 23;

所以我的问题是:是否有正式的参考资料" partial"对象初始化语法中的(即非重构的)赋值语法。我无法在MSDN e.g. Object and Collection Initializers上轻松找到一个,所以我可以权衡这种语法的相对好处和危险吗?

修改

另外,请注意,就像显式语法一样,

Y = { B = 23 }

除非在Y的构造函数中构造B,否则抛出NullReferenceException

IL反汇编:

即。 demo1demo2都会导致此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

我已经放了一个小样本,显示了IdeOne here上的1& 2和3之间的差异

0 个答案:

没有答案