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

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

这是我的示例类:

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 

我总是使用的第二种方法,使用对象初始化器语法:

 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建议第二种方式。 但第三种方式做什么以及什么时候有用呢?

更新 :所以看起来使用最后一种方式似乎是一个糟糕的resharper sugestion,这就是为什么他们改变它同时使用第二种方式。

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

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

 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 }被调用时BahProp = { Id = 1 }

集合初始值设定项也是如此:

 public class Foo { public List Numbers { get; set; } } var foo = new Foo { Numbers = { 1, 2, 3 } }; 

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

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