给定
public class SomeClassWithAList
{
public List<int> list { get; set; }
}
[Fact]
public void InitListInsideModel()
{
var cashthing = new SomeClassWithAList { list = { 4 } };
}
我的问题是InitListInsideModel
似乎是一个有效的代码,但实际上这个代码不会执行。
System.NullReferenceException:对象引用未设置为对象的实例。
这里发生了什么?我不理解什么基本概念?这是编译器错误吗?为什么IntelliSense不警告我不能以这种方式实例化列表?
TLDR
正如您所知,修复方法是以某种方式初始化集合
public List<int> list { get; set; } = new List<T>();
// or
var cashthing = new SomeClassWithAList
{
list = new List<int>(){ 4 }
};
为什么你可以这样做而不会得到警告?好这是一个有趣的问题。
乍一看,它看起来像是一个roslyn错误,它允许在对象initializer内的集合上使用无效的数组初始值设定项语法。
然而,它实际上是经过设计的。语法所做的是使用集合Add
方法的分辨率添加序列。要使其工作,需要初始化集合!
你每天都能学到新东西
以下
var cashthing = new SomeClassWithAList
{
list = { 4 }
};
编译为
new SomeClassWithAList().list.Add(4);
IMO,静态分析应该能够对此发出警告(尤其是对于可为null的类型(,它也应该在对象和集合初始化器(C#编程指南(中得到很好的记录。
我唯一能找到合适文档的地方是C#语言规范
强调矿
7.6.10.2对象初始化程序
成员初始值设定项,在等号是嵌入式集合的初始化而不是为字段或属性、元素指定新集合初始值设定项中给定的被添加到字段或属性。字段或属性必须是集合类型满足§7.6.10.3中规定的要求。
因此,该功能的正确使用是确保您的收藏自动初始化
public List<int> list { get; set; } = new List<T>();
其他资源
在进一步挖掘后,我发现了以下
GitHub问题谈论的确切情况
- C#编译器允许在嵌套对象上使用错误的对象初始值设定项语法
GitHub问题希望在文档中添加更多的特殊性,以澄清的语言功能
- 文档嵌套对象初始值设定项
我认为您需要在某个地方实例化list
。。。
在您当前的任务中:
var cashthing = new SomeClassWithAList { new List<int> list = { 4 } };
或者在list
声明中:
public List<int> list { get; set; } = new List<int>();
或者在SomeClassWithAList
类构造函数中:
public SomeClassWithAList()
{
list = new List<int>();
}
所有这些选项都会编译并运行。