初始化没有“新列表”的列表属性会导致NullReferenceException
using System; using System.Collections.Generic; class Parent { public Child Child { get; set; } } class Child { public List Strings { get; set; } } static class Program { static void Main() { // bad object initialization var parent = new Parent() { Child = { Strings = { "hello", "world" } } }; } }
上面的程序编译很好,但在运行时崩溃, Object引用未设置为对象的实例 。
如果您在上面的代码段中注意到,我在初始化子属性时省略了new 。
显然,正确的初始化方法是:
var parent = new Parent() { Child = new Child() { Strings = new List { "hello", "world" } } };
我的问题是为什么C#编译器在看到第一个构造时不会抱怨?
为什么破坏的初始化有效语法?
var parent = new Parent() { Child = { Strings = { "hello", "world" } } };
第二种语法对readonly属性有效。 如果更改代码以初始化相应构造函数中的Child和Strings属性,则语法有效。
class Parent { public Parent() { Child = new Child(); } public Child Child { get; private set; } } class Child { public Child() { Strings = new List(); } public List Strings { get; private set; } } static class Program { static void Main() { // works fine now var parent = new Parent { Child = { Strings = { "hello", "world" } } }; } }
它没有破坏语法,是你在一个根本没有实例化的属性上使用对象初始化器。 你写的内容可以扩展到
var parent = new Parent(); parent.Child.Strings = new List { "hello", "world" };
抛出NullReferenceException
:您正在尝试分配属性Child
包含的属性,而Child
仍为null
。 使用构造函数首先实例化Child
,处理此问题。
初始化没有任何问题,但它正在尝试初始化不存在的对象。
如果类具有创建对象的构造函数,则初始化有效:
class Parent { public Child Child { get; set; } public Parent() { Child = new Child(); } } class Child { public List Strings { get; set; } public Child() { Strings = new List (); } }
您似乎误解了集合初始化程序的function。
它只是一个语法糖,它将大括号中的列表转换为一系列对Add()
方法的调用,该方法必须在正在初始化的集合对象上定义。
因此,你的= { "hello", "world" }
具有相同的效果
.Add("hello"); .Add("world");
显然,如果未创建集合,则会因NullReferenceException而失败。
始终在编译时检查引用null。 虽然编译器有时会在分配变量之前警告使用变量。 编译器正常工作。 这是一个运行时错误。