C# 属性初始化不调用列表的集合<;T>;

C# 属性初始化不调用列表的集合<;T>;,c#,initializer,C#,Initializer,我在检查类属性的代码覆盖率时发现了一个场景。当属性的类型为List且使用了初始值设定项时,似乎不会调用set方法。对于其他类型,如字符串和整数,情况并非如此。代码覆盖率不会显示set调用,set中的断点也不会被命中 示例类: public class ContainerClass { public string Text { get; set; } public List<Item> Items { get; set; } } 编辑:我想指出,列表是正确分配的,可以

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

示例类:

public class ContainerClass
{
    public string Text { get; set; }
    public List<Item> Items { get; set; }
}
编辑:我想指出,列表是正确分配的,可以根据列表进行测试,但它似乎与实际的set方法有关

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

var arrange = new ContainerClass
{
    Items = new List<Item> { new Item() }
};
var arrange=新的集装箱类
{
Items=新列表{new Item()}
};
您可以执行以下任一操作:

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

    public ContainerClass()
    {
        Items = new List<Item>();
    }
}
或者,如果您没有按照说明使用构造函数,您可以初始化如下列表:

var arrange = new ContainerClass
{
    Items = new List<Item>(){ new Item(){Prop=Value} }
};
var arrange=新的集装箱类
{
Items=new List(){new Item(){Prop=Value}
};
您可以执行以下任一操作:

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

    public ContainerClass()
    {
        Items = new List<Item>();
    }
}
或者,如果您没有按照说明使用构造函数,您可以初始化如下列表:

var arrange = new ContainerClass
{
    Items = new List<Item>(){ new Item(){Prop=Value} }
};
var arrange=新的集装箱类
{
Items=new List(){new Item(){Prop=Value}
};
当使用初始值设定项时,如下面所示,会调用Text上的set方法,并在代码覆盖率中注册,但Items上的set方法不会,我想知道为什么:

var arrange = new ContainerClass
{
    Text = "value",
    Items = { new Item() }
};
这是因为在调用集合初始值设定项时,实际上并未初始化项列表。根据规范第7.6.10.2节:

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

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

为了使代码运行时不会出错,项必须已经初始化。这可能发生在属性声明本身中(假设它是自动实现的属性):

公共类容器类
{
公共字符串文本{get;set;}
公共列表项{get;set;}=new List();
}
或者在构造函数中(您尚未显示):

公共类容器类
{
公共字符串文本{get;set;}
公共列表项{get;set;}
公共集装箱类()
{
项目=新列表();
}
}
否则,当程序尝试计算集合初始值设定项时,代码将抛出NullReferenceException

根据您的语句,setter从不为项调用,它很可能是在属性声明中初始化的(如果它实际上不是自动实现的属性,则在backing字段中)。如果它在构造函数中被初始化,setter仍然会被调用

您的第二个示例导致调用setter,因为您确实在为那里的项分配一个新列表

当使用初始值设定项时,如下面所示,会调用Text上的set方法,并在代码覆盖率中注册,但Items上的set方法不会,我想知道为什么:

var arrange = new ContainerClass
{
    Text = "value",
    Items = { new Item() }
};
这是因为在调用集合初始值设定项时,实际上并未初始化项列表。根据规范第7.6.10.2节:

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

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

为了使代码运行时不会出错,项必须已经初始化。这可能发生在属性声明本身中(假设它是自动实现的属性):

公共类容器类
{
公共字符串文本{get;set;}
公共列表项{get;set;}=new List();
}
或者在构造函数中(您尚未显示):

公共类容器类
{
公共字符串文本{get;set;}
公共列表项{get;set;}
公共集装箱类()
{
项目=新列表();
}
}
否则,当程序尝试计算集合初始值设定项时,代码将抛出NullReferenceException

根据您的语句,setter从不为项调用,它很可能是在属性声明中初始化的(如果它实际上不是自动实现的属性,则在backing字段中)。如果它在构造函数中被初始化,setter仍然会被调用


您的第二个示例导致调用setter,因为您确实在为其中的项分配一个新列表。

初始化它的正确方法是在您的上一个示例中,我不确定其他版本的含义。该列表从未为我分配-导致NullReferenceException。§7.6.10.2“在等号后指定集合初始值设定项的成员初始值设定项是嵌入式集合的初始化。将初始值设定项中给定的元素添加到字段或属性引用的集合中,而不是将新集合指定给字段或属性。“为了让代码正常工作,您的列表正在其他地方初始化-您给出的示例无法正确运行。正如@BoltClock所指出的,我的问题不包括我使用的实际场景,我已使用新列表在属性声明上设置了值。正确的w