鉴于以下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反汇编:
即。 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
我已经放了一个小样本,显示了IdeOne here上的1& 2和3之间的差异