在对象初始值设定项中使用数组初始化程序时的NRE

时间:2015-05-21 19:55:05

标签: c# .net

在以下情况下使用数组初始值设定项时,我观察到一些奇怪的行为(在VS2013中测试过):

    class A
    {
        public List<int> Items { get; set; }
    }

    void Main(string[] args)
    {
        // (1) it compiles, but failing with NRE in runtime
        var a = new A { Items = { 1, 2, 3 } };

        // (2) it does not compile, as expected
        List<int> b = { 1, 2, 3 };
    }

实际上我希望在案例(1)中出现编译器错误,与我在案例(2)中的错误相同:Can only use array initializer expressions to assign to array types. Try using a new expression instead.但是案例(1)编译没有任何问题,并且可以预期失败{{1运行时。有人可以解释为什么编译器允许案例(1)?

1 个答案:

答案 0 :(得分:1)

以下是C#规范的相关引用(第5版,第7.6.10.2节):

  

在等号后面指定集合初始值设定项的成员初始值设定项是嵌入式集合的初始化。 不是将新集合分配给字段或属性,而是将初始值设定项中给出的元素添加到字段或属性引用的集合中。字段或属性必须是满足以下条件的集合类型。 §7.6.10.3中规定的要求。

因为您在对象初始值设定项中使用了集合初始值设定项,行为是不同的,并且此代码:

var a = new A { Items = { 1, 2, 3 } };

编译成这样的东西(你可以通过查看IL来验证这一点):

var a = new A();
a.Items.Add(1);
a.Items.Add(2);
a.Items.Add(3);

这当然会抛出NullReferenceException,因为Items为空。

您可以通过向类A添加构造函数来修复崩溃:

class A
{
    public List<int> Items { get; set; }
    public A() { Items = new List<int>(); }
}