为什么不允许重新分配集合初始值设定项?

问题描述 投票:0回答:2

我一直认为这两种方式都效果很好。然后做了这个测试,发现重新分配是不允许的:

int[] a = {0, 2, 4, 6, 8};

工作正常,但不是:

int [ ] a;
a = { 0, 2, 4, 6, 8 };

这有什么技术原因吗?我想我应该在这里问一下,因为这种行为是我直观地预期的。

c# .net collections collection-initializer
2个回答
21
投票

首先,让我们正确理解条款。这不是一个 collection 初始化器。这是一个数组初始值设定项。集合初始值设定项始终遵循集合类型的构造函数。数组初始值设定项仅在本地或字段声明初始值设定项或数组创建表达式中才合法。

您注意到这是一个奇怪的规则,这是完全正确的。让我准确地描述一下它的怪异之处:

假设您有一个方法 M,它接受一个整数数组。所有这些都是合法的:

int[] x = new[] { 10, 20, 30 };
int[] y = new int[] { 10, 20, 30 };
int[] z = new int[3] { 10, 20, 30 };
M(new[] { 10, 20, 30 });
M(new int[] { 10, 20, 30 });
M(new int[3] { 10, 20, 30 });

但是

int[] q = {10, 20, 30}; // legal!
M( { 10, 20, 30 } ); // illegal!

似乎“单独”数组初始值设定项在“装饰”数组初始值设定项所在的任何地方都应该是合法的,或者在任何地方都应该是合法的。奇怪的是,这个伪表达式仅在初始化器中有效,而在表达式合法的其他任何地方都无效。

在我批评和捍卫这一选择之前,我首先想说的是,这种差异是一个历史偶然。没有令人信服的充分理由。如果我们能够在不破坏代码的情况下摆脱它,我们就会这么做。但我们不能。如果我们今天再次从头开始设计 C#,我认为没有“new”的“单独”数组初始值设定项很可能不是有效的语法。

因此,让我首先给出一些理由,说明为什么数组初始值设定项不应该被允许作为表达式,而应该在局部变量初始值设定项中被允许。然后我会给出一些相反的理由。

不允许数组初始值设定项作为表达式的原因:

数组初始值设定项违反了

{
始终意味着引入新代码块的良好属性。 IDE 中的错误恢复解析器会在您键入时进行解析,喜欢使用大括号作为判断语句何时不完整的便捷方法;如果你看到:

if (x == M(
{ 
   Q(

那么代码编辑器很容易猜测您在

))
之前缺少
{
。编辑器会假设
Q(
是语句的开头,而缺少结尾。

但是,如果数组初始值设定项是合法表达式,那么可能缺少的是

)})){}
following
Q

其次,数组初始值设定项作为表达式违反了所有堆分配在某处都有“new”的好原则。

字段和本地初始化器中应允许使用数组初始化器的原因:

请记住,数组初始值设定项是在隐式类型局部变量、匿名类型或数组类型推断之前添加到 v1.0 语言中的。回到过去,我们没有令人愉快的“new[] { 10, 20, 30}”语法,因此如果没有数组初始值设定项,您必须说:

int[] x = new int[] { 10, 20, 30 };

这看起来非常多余!我明白为什么他们想把“new int[]”从那里取出来。

当你说

int[] x = { 10, 20, 30 };

它在语法上没有歧义;解析器知道这是一个数组初始值设定项,而不是代码块的开头(与我上面提到的情况不同)。它也不是类型模糊的;很明显,初始化器是来自上下文的整数数组。

因此,这个论点证明了为什么在 C# 1.0 中,本地和字段初始值设定项允许使用数组初始值设定项,但表达式上下文中不允许使用。

但这不是我们今天所处的世界。如果我们今天从头开始设计它,我们可能不会有没有“new”的数组初始值设定项。现在我们当然意识到更好的解决方案是:

var x = new[] { 10, 20, 30 };

并且该表达式在任何上下文中都有效。如果您认为合适,您可以在

=
的“声明”侧或“初始化器”侧显式键入它,或者您可以让编译器推断任一侧或两侧的类型。

所以,总结一下,是的,你是对的,数组初始值设定项只能在本地和字段声明中,而不能在表达式上下文中,这是不一致的。十年前这是有充分理由的,但在具有类型推断的现代世界中,不再有充分的理由了。目前这只是一个历史意外。


1
投票

最有可能的是:

    int [] a;// ={1,2,3,4};
    a = new [] {1, 2, 3, 4};

在VB中的工作方式与声明相同,更容易xD

Dim a() As Integer '={1,2,3,4}
a = {1, 2, 3, 4}
© www.soinside.com 2019 - 2024. All rights reserved.