为什么我不能将数组初始值设定项与隐式类型变量一起使用?

时间:2011-09-08 16:32:48

标签: c# arrays compiler-construction implicit-typing

为什么我不能将数组初始值设定项与隐式类型变量一起使用?

string[] words = { "apple", "strawberry", "grape" };                 // legal
string[] words = new string[]{ "apple", "strawberry", "grape" };     // legal
var words = new []{ "apple", "strawberry", "grape" };                // legal
var words = new string[]{ "apple", "strawberry", "grape" };          // legal

var words = { "apple", "strawberry", "grape", "peach" };             // ILLEGAL

此限制是否存在技术原因?为什么不能像它那样推断出类型:

var number = 10;
var text = "Hello";

编译器清楚地知道我要做什么,它只是不允许它:

  

CS0820:无法将数组初始值设定项分配给隐式类型的本地


更新:我使用四种合法的数组声明方法编译了一个程序,它生成了相同的IL:http://pastebin.com/28JDAFbL

这只会增加我的困惑。并且“就像这样,因为规范说的如此”没什么帮助。为什么规格是这样的?这里的理由是什么?

3 个答案:

答案 0 :(得分:33)

  

为什么我不能将数组初始值设定项与隐式类型变量一起使用?为什么规格是这样的?这里的理由是什么?

在做出这个决定时,我不在设计团队中,设计说明(*)对此主题保持沉默。但是,我在2005年做出这个决定的时候问了一个在房间里的人。

解释平淡无奇。首先,设计团队对数组初始化程序语法一直不满意。坦率地说,数组初始值设定项不是表达式并且语法上只能出现在本地或字段声明中,这是完全奇怪的。它使解析器复杂化。

似乎很奇怪
int[] x = {1};

应该是合法的,但

M({1});

不是。

阵列初始化语法还使编辑时代码分析期间的错误恢复变得复杂。假设你有类似的东西:

class C
{
    void M()
    {
        {
            int result = whatever();
            ...
        }
        {
            int result = somethingElse();
            ...
        }
    }
}

然后开始在编辑器中输入新的声明:

    void M()
    {
        int[] x = 
        {
            int result = whatever();

突然之间,解析器必须以一种不会混淆即将输入“null;”的不良用户的方式消除歧义。显然,您并不打算使用代码块初始化局部变量,但是解析器完全有权说这个大括号只能合法成为数组初始值设定项的一部分,因此它是“意外的结果”。

所以,长话短说,“经典”阵列初始化器有点像错误。由于向后兼容的原因,我们无法摆脱它们。但我们也不想通过在更多位置允许它们来鼓励使用它们。

设计团队提出了将“new []”添加到数组初始值设定项的想法,并将 转换为合法表达式,现在问题就解决了。经典的数组初始化器错误没有“蠕变”到语言的新区域,并且有一种简洁但可读的语法清楚地表明“你在这里制作一个新数组”。

故事的寓意是:第一次尝试正确,因为语法是永远的。


(*)在我的搜索中,我确实发现了一些有趣的事情:团队最初认为“var”可能不是为该功能选择的关键字;显然它在他们身上成长。另外,一种设计要求“var”本地不仅要隐式输入,还要初始化为本地。显然我们从未实现过init-once本地人。

答案 1 :(得分:5)

您可以使用以下语法执行此操作:

var words = new[] { "apple", "strawberry", "grape", "peach" };

答案 2 :(得分:4)

可能是因为你没有给它任何类型,例如。是数组,列表还是其他一些集合。

然而,这种方法看起来相同,而且只有几个字符更长。

var words = new[]{ "apple", "strawberry", "grape", "peach" };