c# - 为什么数组初始值设定项不适用于局部变量?
问题描述
为什么可以在没有编译器错误的情况下执行以下操作:
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[]
不再编译时,第二个示例可以。
谢谢!
解决方案
这里的混淆来自于相同的语法在不同的上下文中被视为不同。在对象初始化器中,表达式表示一个集合初始化器。
该规范将集合初始化器定义为:
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
像在数组初始化程序中一样为您添加,但它可能有其他副作用。例如,如果您在构造函数中初始化列表,它将覆盖该列表。所以我想这就是为什么它是这样的。
推荐阅读
- swift - AVPlayer 音频锁屏更新停止工作,只有在另一个 AVPlayer 实例播放视频内容后
- python-3.x - WordCloud“模块”对象不可调用Python3
- spring - Spring boot security中授权服务关闭时的授权错误处理不起作用
- php - Slim PHP:如何根据用户 ID 进行 POST 或 PUT?
- django - Django 权限
- apache - .htaccess 重写规则不能与 index.php 正确工作?路径
- visual-studio - Visual Studio - 带有快捷键或文本的完整按键序列
- firebase - 颤振问题:“时间戳”类型不是“日期时间”类型的子类型
- php - cURL PHP 脚本可以在除 iPhoneq 之外的任何地方使用
- java - 讲解Euler's Totient Implementation的实现