我正在尝试在C#中编译以下代码:
String[] words = {"Hello", "Worlds"};
words = {"Foo", "Bar"};
我收到编译错误,如:
Error 1 Invalid expression term '{'
Error 2 ; expected
Error 3 Invalid expression term ','
另一方面,如果我尝试
String[] words = { "Hello", "Worlds" };
words = new String[] {"Foo", "Bar"};
编译好。根据{{3}},
int[] a = {0, 2, 4, 6, 8};
它只是等效数组创建表达式的简写:
int[] a = new int[] {0, 2, 4, 6, 8};
为什么不编译第一个代码示例?
答案 0 :(得分:10)
正确,只有声明才允许使用短初始值设定语法。不在正常的声明中。
String[] words = new string[]{ "Hello", "Worlds" }; // full form
String[] words = { "Hello", "Worlds" }; // short hand, special rule
words = {"Foo", "Bar"}; // not allowed
words = new String[] {"Foo", "Bar"}; // allowed, full form again
只有在用作声明的(rhs)部分时才允许使用简写符号。
答案 1 :(得分:5)
C#spec 12.6数组初始值设定项
在字段或变量声明中,数组类型是声明的字段或变量的类型。在字段或变量声明中使用数组初始值设定项时,例如: int [] a = {0,2,4,6,8}; 它只是等效数组创建表达式的简写: int [] a = new int [] {0,2,4,6,8};
String[] words = { "Hello", "Worlds" };
是声明,但
words = {"Foo", "Bar"};
不是。
答案 2 :(得分:2)
根据相同的MSDN页面,此语法特定于数组变量初始化;它不是通用的数组语法。
然而,这很接近:
String[] words = { "Hello", "Worlds" };
// words = {"Foo", "Bar"};
words = new[] {"Foo", "Bar"};
答案 3 :(得分:2)
您指的编译器错误是由无效语法引起的。
// variable declaration so constructor may be assumed
String[] words = { "Hello", "Worlds" };
// attempted variable assignment using invalid syntax
words = {"Foo", "Bar"};
// explicit constructor
words = new String[] {"Foo", "Bar"};
// as a note this would also work. Here the type of the array is assumed.
words = new [] {"Foo", "Bar"};
答案 4 :(得分:1)
根据您链接的文档,数组初始值设定项仅在字段或变量声明中有效 - 对于变量赋值,您必须事先指定new[]
:
在数组创建表达式(一般情况)中,数组类型紧跟在初始化程序之前。在字段或变量声明中,数组类型是要声明的字段或变量的类型。
答案 5 :(得分:1)
作为变量声明的一部分使用的数组初始化器基本上是特殊的。 (我现在无法查找规范引用,但我可以在以后这样做。)在变量声明之外,编译器并没有真正注意到有一个赋值的事实 - 右边的表达式一方必须站在自己的两只脚上。 1
在C#3中,您可以使用略微缩写的形式:
words = new[] {"Foo", "Bar"};
这将从其中的元素推断数组的类型(在编译时)...并且假设它与目标变量兼容,则赋值将起作用。此语法在更一般的上下文中工作 - 您可以使用它将数组作为方法参数传递,例如。
但是,无法在变量声明之外使用“完全缩写”形式。
1 不可否认,有些表达式没有类型,例如lambda表达式。
答案 6 :(得分:0)
在初始化期间,您将明确声明数组的类型,这使得此简写清晰且明确。然而,稍后在代码中,一点点歧义开始蔓延。例如,理论上,你可以尝试建立一个对象数组。当然,你可能希望它是一个字符串数组,但为了避免逻辑错误,编译器不想假设这样的东西,除非你非常清楚你想要的是什么做。