首页 > 解决方案 > 为什么数组初始值设定项不适用于局部变量?

问题描述

为什么可以在没有编译器错误的情况下执行以下操作:

private class Foo
{
     public List<string> Bar { get; set; }
}

private void SomeRandomMethod(){
    var test2 = new Foo
    {
         Bar = { "test", "test2" }
    };
}

但这不起作用?

List<string> test = { "test", "test2" };

我知道我可以写new { "test", "test2" };,然后就可以了。对于这个问题,我不想要解决方法或解决方案或类似的东西,而是想解释一下这两种情况的区别究竟是什么。

编辑:将类型从第一个示例更改List<string>string[]不再编译时,第二个示例可以。

谢谢!

标签: c#

解决方案


这里的混淆来自于相同的语法在不同的上下文中被视为不同。在对象初始化器中,表达式表示一个集合初始化器

该规范将集合初始化器定义为:

7.6.10.3 集合初始化器

集合初始化器由一系列元素初始化器组成,由 { 和 } 标记括起来并用逗号分隔。每个元素初始化器指定一个要添加到正在初始化的集合对象的元素,并由一个由 { 和 } 标记括起来并用逗号分隔的表达式列表组成。

在同一章的后面:

对于按顺序指定的每个元素,集合初始值设定项在目标对象上调用 Add 方法,并将元素初始值设定项的表达式列表作为参数列表,对每个调用应用正常的重载决议。

所以这就是你在第一个例子中得到 NRE 的原因。由于您在使用集合初始化程序之前没有添加 a new List<string>,因此您正在尝试调用Add一个null对象。您将需要new List<string>在构造函数中添加或执行此操作。

数组初始值设定项是不同的,当您省略new那里时,编译器只会为您添加新的,所以:

string[] values = { "foo", "bar" };

相当于:

string[] values = new [] { "foo", "bar" };

当您{ "foo", "bar" }在对象初始化程序之外使用时,您会收到错误,因为您试图将数组分配给列表。

注意:在集合初始化程序中,您可能希望编译器更智能,并new像在数组初始化程序中一样为您添加,但它可能有其他副作用。例如,如果您在构造函数中初始化列表,它将覆盖该列表。所以我想这就是为什么它是这样的。


推荐阅读