在对象初始化程序中的嵌入集合上使用集合初始化程序时没有警告

  • 本文关键字:程序 初始化 集合 警告 对象 c# .net
  • 更新时间 :
  • 英文 :


给定

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>();
}

所有这些选项都会编译并运行。

最新更新