我在以下代码中遇到了运行时NullReferenceException
异常:
public class Container
{
public IList<string> Items { get; set; }
}
class Program
{
static void Main(string[] args)
{
var container = new Container() { Items = {"Test"} };
}
}
compiller无法创建交互式实例,但我得到了运行时异常,而不是编译时,这是合乎逻辑的。当我进一步研究这种行为时,我更加困惑:
var container = new Container() { Items = {} }; //Legal, Items is null after initialization
var container = new Container() { Items = { "Test" } }; //Legal, throws exception
container.Items = {}; //Illegal doesn't compile
container.Items = {"Test"}; //Illegal doesn't compile
这是某种错误还是我不明白? 我正在使用.net framework 4.0
答案 0 :(得分:3)
它编译,因为编译器不知道是List
已在其他地方初始化。您可以通过在构造函数中添加初始化来使其工作:
public class Container
{
public IList<string> Items { get; set; }
public Container()
{
Items = new List<string>();
}
}
或者更改属性以隐藏在创建类实例时初始化的字段:
private IList<string> items = new List<string>();
public IList<string> Items
{
get { return items; }
set { items = value; }
}
然后,var container = new Container() { Items = { "Test" } };
工作正常。
在运行时.Add()
为集合初始化程序组中的每个项调用方法。如果未使用new List<string>
初始化属性,则其值为null
,这就是抛出NullReferenceException
的原因。
Object and Collection Initializers (C# Programming Guide)
通过使用集合初始值设定项,您不必指定多个 在源代码中调用类的Add方法; 编译器 添加了电话。
答案 1 :(得分:0)
您没有初始化List
var container = new Container() { Items = new List<string>() { "Test" } };
顺便说一句,下面的编译器是合法的,它没有任何问题(语法正确等)
var container = new Container() { Items = {} };
但是因为编译器不知道Items
列表尚未初始化(您没有传递集合初始化器{}
中的任何项),.Add
方法将不会调用List
并且运行时将不知道Items
对象为空
另一方面,下面对于编译器来说是合法的,但它在运行时抛出一个异常,因为你试图初始化传递一个项目的列表(由于上面解释的原因,编译器是正确的)所以当运行时将调用场景后面的.Add
方法,它将抛出一个空引用异常,因为Items
尚未初始化
var container = new Container() { Items = { "Test" } };