为什么这个错误的对象初始化用花括号甚至编译?

sur*_*ace 3 c# object-initializers curly-braces

Whille为WPF/MVVM项目的集合创建了一些虚拟数据,我生成了以下错误代码,编译得很好,但在运行时抛出异常.

有一个嵌套的数据对象结构,我错误地只用花括号进行实例化(看起来像编写JavaScript确实会对大脑造成永久性损害).

using System.Collections.ObjectModel;

namespace testapp
{
    class Program
    {
        static void Main(string[] args)
        {
            var collection = new ObservableCollection<TopLevelDataObject>();
            collection.Add(new TopLevelDataObject{Nested = {Bar = 5}});         // NullReferenceException
        }

        class TopLevelDataObject
        {
            public NestedDataObject Nested { get; set; }
            public string Foo { get; set; }
        }

        class NestedDataObject
        {
            public double Bar { get; set; }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

为什么要编译?

如果我创建一个匿名类型,比如Nested = new {Bar = 5},我在编译期间收到错误消息(因此失败):

Cannot implicitly convert type '<anonymous type: int Bar>' to 'testapp.Program.NestedDataObject'
Run Code Online (Sandbox Code Playgroud)

为什么在省略new运算符时没有出现这样的错误?

它甚至为我提供了该属性的代码提示: 点击查看图片,因为我还没有足够的代表来嵌入它

我的猜测就是这{Bar = 5}只是一个代码块,它本身就是一个有效的东西.但为什么将代码块分配给任何东西(在这种情况下,Nested属性)是有效的?

Pat*_*man 5

为什么要编译?

因为在编译代码时,它只被编译为一组赋值操作.它并非都是您创建的新实例.

如果Nested从构造函数构造新实例,则可以为其分配值Nested.Bar.

更改public NestedDataObject Nested { get; set; }为此以查看其工作原理:

public NestedDataObject Nested { get; } = new NestedDataObject();
Run Code Online (Sandbox Code Playgroud)

(注意,您永远不能Nested在上面的代码中将值赋给构造函数外部!)