NullReferenceException,带有resharper建议的对象初始值设定项

时间:2016-07-14 09:05:36

标签: c# initialization resharper c#-6.0

我对象初始化器语法有一个奇怪的问题。

以下是我的示例课程:

public class Foo
{
    public Bah BahProp { get; set; }
}

public class Bah
{
    public int Id { get; set; }
}

考虑以下三种初始化对象的方法:

旧的,冗长但明确的方式,正常工作:

var foo1 = new Foo();
foo1.BahProp = new Bah();
foo1.BahProp.Id = 1;
// correctly initialized

我总是使用object initializer语法的第二种方式:

var foo2 = new Foo
{
    BahProp = new Bah { Id = 1 }
}; // correctly initialized

第三种方式resharper建议我的同事使用不同的resharper版本(这是一个bug吗?):

var foo3 = new Foo
{
    BahProp = { Id = 1 }
};  // NullReferenceException

最后一种做法有何不同?

我的resharper版本是2016.1.1,我的同事是在10.02。我的resharper提出了第二种方式。但第三种方式做什么以及什么时候有用?

更新:因此,使用最后一种方式似乎是一个糟糕的重新解决方案,这就是为什么他们同时改变它以使用第二种方式。

如果要通过初始化内联或构造函数中引用类型的所有属性/字段,可以使用第三种方法来避免使用NullReferenceException

我绝对不会使用这种奇怪的属性赋值语法。

1 个答案:

答案 0 :(得分:6)

new Foo { BahProp = { Id = 1 } }

汇编为:

new Foo().BahProp.Id = 1;

或者,更详细一点:

var foo3 = new Foo();
foo3.BahProp.Id = 1;

所以BahProp是空的。你不是构建它 (这可能是所有C#中最令人困惑的语法)
选项2有效,因为您正在调用Bah的构造函数。

如果在Foo的构造函数中初始化BahProp,选项3也会起作用。它将在BahProp = { Id = 1 }被调用的时间构建。

收集初始化器也是如此:

public class Foo {
    public List<int> Numbers { get; set; }
}

var foo = new Foo { Numbers = { 1, 2, 3 } };

这不会初始化List。它只调用Add on it。

您必须将new MyObject() { X = 1, Y = 2 }视为两个不同的部分:
new MyObject()构造一个新对象和
{ X = 1, Y = 2 }设置其属性的值(这就是它所做的全部) 可以嵌套对象和集合初始值设定项。顶级初始值设定项必须遵循构造函数,但嵌套初始值设定项不能。