14

我一直认为这两种方式都很好。然后做了这个测试,并意识到它不允许重新分配:为什么重新分配的集合初始化器不被允许?

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

工作正常,但不是:

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

任何技术原因?我想我会在这里问这个问题,因为这个行为是我直觉上预期的。

+4

您可能会发现这有帮助:http://stackoverflow.com/questions/7351453/why-cant-i-use-the-array-initializer-with-an-implicitly-typed-variable(不严格是重复的) – 2011-12-23 22:45:22

回答

20

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

你完全正确地注意到这是一条奇怪的规则。让我准确地描述它的奇怪:

假设你有一个方法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#,我认为没有“新”的“孤立”数组初始化器不会是有效的语法是很好的。

所以,让我先给一些原因,数组的初始化不应该被允许为表达式,应在局部变量初始化被允许。那么我会给出一些相反的理由。

原因数组的初始化不应该被允许作为表达式:

数组初始违反了不错的属性,{总是意味着引进新的代码块。 IDE中的错误恢复解析器在您输入时解析时喜欢使用大括号作为判断语句何时不完整的便捷方式;如果你看到:

if (x == M(
{ 
    Q(

然后,它是很容易的代码编辑器来猜你是在{前失踪))。编辑会认为Q(是一个陈述的开始,并且它没有结束。

但如果数组的初始化是合法的表情那么它可能是缺什么是)})){}以下Q

其次,作为表达式的数组初始化符违反了所有堆分配在其中某处具有“新”的好原则。

原因数组的初始化应该在外地和本地初始化被允许:

请记住,数组的初始化添加到了V1.0的语言,之前隐式类型的当地人,匿名类型,或类型推断的阵列。早在一天,我们没有愉快的“新[] {10,20,30}”语法,所以没有数组的初始化,你不得不说:

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

这似乎很多余的!我可以明白为什么他们想从那里得到那个“new int []”。

当你说

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

它在语法上不明确;解析器知道这是一个数组初始化器,而不是代码块的开始(不像上面提到的那种情况)。它也不是类型模糊的;很显然,初始化器是来自上下文的整数数组。

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

但是,这并不是我们在当今世界。如果我们今天从头开始设计,我们可能不会有没有“新”的数组初始化器。当然,现在我们认识到,更好的解决方案是:

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

和表达是有效的在任何情况下。如果您认为合适,您可以在=的“声明”一侧或“初始化程序”一侧明确键入它,也可以让编译器推断两侧或两侧的类型。

因此,总结,是的,你说得对,数组初始值设定项只能在本地和字段声明中,而不是在表达式上下文中是不一致的。这十年前有一个很好的理由,但在现代世界中,类型推理已经不再有很好的理由。这只是一个历史事故。

+4

哇。如果您发布了每个C#问题的答案,StackOverflow将会是1000倍以上。 – 2011-12-24 01:22:37

+0

@JimSchubert:我非常欣赏这种情绪,但我向你保证情况会更糟。我不知道网站上99%的C#问题的答案!我是该语言的历史,设计和实施方面的专家;在过去的六年中关注于这一点意味着我有许多实际的C#编程方面的知识,而我几乎不知道这一点。 – 2011-12-24 01:55:16

+0

无论如何,爱阅读你的答案! – Matthias 2011-12-24 03:54:42

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} 
+1

他在问为什么这个限制存在。 – 2011-12-23 22:57:36

+0

谢谢,以前添加'new []'使它工作。但是,为什么这种限制存在时,它可以在没有它的工作(就像当你第一次给它分配) – 2011-12-23 22:59:39

+0

嗯,我觉得这只是语言,因为在VB中是可以做到的,我们应该看看MSIL代码生成什么是性差异。 – Piyey 2011-12-23 23:03:35