对象初始化期间接口集合成员奇怪的行为

时间:2013-03-20 09:53:20

标签: c# .net initializer

我在以下代码中遇到了运行时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

2 个答案:

答案 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" } };