![](/img/trans.png)
[英]Why can't I declare an implicitly typed array without an initializer?
[英]Can't understand why array initializer in object initializer cannot compiled
我在对象初始化程序中使用数组初始化程序时看到了NRE,并且进行了更新和https://github.com/dotnet/roslyn/wiki/New-Language-Features-in-C%23-6#extension-add-methods- in-collection-initializers,但我还是不明白。
var arr = new int[] { 1, 2, 3 }
使用stelem
生成IL代码。 但是int[] arr = { 1, 2, 3 }
使用RuntimeHelpers.InitializeArray
生成IL代码。 我认为它使用的是Array.Add
扩展方法。
但是在对象初始化程序中,所有数组初始化程序都会生成第二个代码。 一个例子,
new A() {
arr = new int[] { 1, 2, 3 }
}
数组arr
也使用RuntimeHelpers.InitializingArray
创建。 然后,这是否意味着下一个代码没有任何问题?
new A() {
arr = { 1, 2, 3 } // Compiler error!
}
与旧版本的c#编译器不同,它使编译器出错,说system.array does not contain a definition for Add
。 发生了什么?
EDIT
我以为没有new []
语法会产生差异,但实际上,三个以上的元素会产生不同的IL代码。
第二种语法( { arr = {... } }
)是value.arr.Add(.)
序列的语法糖-大概value.arr
没有在构造函数中初始化,因此未初始化。
假设A
为:
class A {
public int[] arr {get;set}
}
然后
var x = new A() {
arr = { 1, 2, 3 } // Compiler error!
};
是相同的
var x = new A(); // note x.arr is default null here
x.arr.Add(1); // NRE is arr is list, can't compile for int[]
x.arr.Add(2);
x.arr.Add(3);
修复:使用列表,没有合理的方法将元素添加到数组中。 如果使用的其他类型没有.Add
,请执行该代码可见的扩展方法。
为什么使用new
版本:
var x = new A() {
arr = new int[] { 1, 2, 3 }
};
等价于*
var x = new A();
x.arr = new int[] { 1, 2, 3 };
请注意,在数组初始化程序中,可以使用两种语法达到相同的效果,但不能在数组字段的初始化程序中使用( 所有可能的C#数组初始化语法 )
int[] x = { 10, 20, 30 }; // valid, same as int[] x = new int[]{ 10, 20, 30 };
而new A { arr = { 10, 20, 30} }
是不一样的new A { arr = new int[3]{ 10, 20, 30} }
在表达式上下文中,这些是合法的数组值:
new int[3] { 10, 20, 30 }
new int[] { 10, 20, 30 }
new[] { 10, 20, 30 }
在局部变量或成员变量初始化器上下文中,这是一个合法的数组初始化器:
int[] x = { 10, 20, 30 };
这是一个合法的集合初始化器 :
List<int> x = new List<int> { 10, 20, 30 };
并且,如果X<T>
是IEnumerable<T>
并具有方法Add(T, T, T)
,则这是合法的:
X<int> x = new X<int> { { 10, 20, 30}, {40, 50, 60} };
但是在成员或集合初始值设定项上下文中,这不是合法的数组属性初始值设定项:
new A() {
arr = { 10, 20, 30 }
}
(请注意,我在这里https://stackoverflow.com/a/5678393/88656总结并评论了数组的规则)
据我了解,问题是“为什么不呢?”
答案是“没有充分的理由”。 这只是C#语法以及对象和集合初始化程序的规则的奇怪之处。
我曾多次考虑过解决这种奇怪的问题,但是与我的时间总是有更好的关系。 该解决方案基本上没有人受益,因为解决方法非常简单。
我猜想,除了仍有大约一百万个其他功能可以更好地利用他们的时间这一事实之外,没有什么可以阻止C#团队设计,指定,实现,测试和发布这些功能。
如果您对此有强烈的兴趣,那么编译器是开源的。 随时提出该功能并对其进行提倡。 或者,为此,实施它并提交拉取请求。 ( 当你提出的功能。)
在实现所需的功能之前,您只需要使用上面列出的三种“表达式”形式之一。 这样做并不麻烦。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.