属性初始化不会为List 调用set

我在检查类属性的代码覆盖时发现了一个场景。 当属性是List 类型,并且使用初始化程序时,似乎不会调用set方法。 对于其他类型,例如字符串和整数,情况并非如此。 代码覆盖率不显示set调用,set中的断点也不会被触发。

示例类:

public class ContainerClass { public string Text { get; set; } public List Items { get; set; } } 

当使用初始化程序时,如下所示,调用Text上的set方法,并在代码覆盖率中注册,但是Items上的set方法没有,我想知道为什么:

 var arrange = new ContainerClass { Text = "value", Items = { new Item() } }; 

编辑:我会指出列表已正确分配,可以进行测试,但它似乎绕过实际的set方法。

有趣的是,当我指定新列表时,它会被调用:

 var arrange = new ContainerClass { Items = new List { new Item() } }; 

当使用初始化程序时,如下所示,调用Text上的set方法,并在代码覆盖率中注册,但是Items上的set方法没有,我想知道为什么:

这是因为在调用集合初始化程序时,Items列表实际上并未初始化。 从规范的7.6.10.2节:

在等号后面指定集合初始值设定项的成员初始值设定项是嵌入式集合的初始化。 而不是将新集合分配给字段或属性,初始化程序中给出的元素将添加到字段或属性引用的集合中。

这意味着集合初始化程序假定集合已经被实例化(即使在对象初始化程序之外也是如此)。 请记住,集合初始值设定项只不过是一系列.Add()调用。

为了使您的代码无错误地运行,必须已经初始化了Items。 这可能发生在属性声明本身(假设它是一个自动实现的属性):

 public class ContainerClass { public string Text { get; set; } public List Items { get; set; } = new List(); } 

或者在构造函数中(您没有显示):

 public class ContainerClass { public string Text { get; set; } public List Items { get; set; } public ContainerClass() { Items = new List(); } } 

否则,当程序尝试评估集合初始值设定项时,您的代码将抛出NullReferenceException。

根据你的声明,setter永远不会被物品调用,它可能是在属性声明(或支持字段,如果它实际上不是自动实现的属性)中初始化的。 如果它在构造函数中初始化,那么仍然会调用setter。

你的第二个例子导致调用setter,因为你确实为那里的Items分配了一个新的列表。

你可以这样做:

 public class ContainerClass { public string Text { get; set; } public List Items { get; set; } public ContainerClass() { Items = new List(); } } 

然后:

 var arrange = new ContainerClass { Text = "SomeValue" }; arrange.Items.Add(new Item(){Prop=Value}); 

或者,如果您不使用所述的构造函数,则可以初始化列表,如下所示:

 var arrange = new ContainerClass { Items = new List(){ new Item(){Prop=Value} } };