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

Ail*_*lyn 16 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
Run Code Online (Sandbox Code Playgroud)

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

var number = 10;
var text = "Hello";
Run Code Online (Sandbox Code Playgroud)

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

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


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

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

Eri*_*ert 33

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

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

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

int[] x = {1};
Run Code Online (Sandbox Code Playgroud)

应该是合法的,但是

M({1});
Run Code Online (Sandbox Code Playgroud)

不是.

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

class C
{
    void M()
    {
        {
            int result = whatever();
            ...
        }
        {
            int result = somethingElse();
            ...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

    void M()
    {
        int[] x = 
        {
            int result = whatever();
Run Code Online (Sandbox Code Playgroud)

突然之间,解析器必须以一种不会混淆即将键入"null;"的不良用户的方式消除歧义.显然你不打算用代码块初始化局部变量,但是解析器完全有权说这个大括号在这里只能合法地成为数组初始化器的一部分,因此它是"int结果"出乎意料.

所以,长话短说,"经典"阵列初始化器有点像错误.由于向后兼容的原因,我们无法摆脱它们.但我们也不想鼓励他们在更多地方使用它们.

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

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


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

  • "试着在第一时间做到正确,因为语法是永远的." 或者像Python一样:如果你没有在第一次就做对,那就是向后兼容. (5认同)

Bre*_*ell 6

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

var words = new[] { "apple", "strawberry", "grape", "peach" };
Run Code Online (Sandbox Code Playgroud)


小智 5

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

但是,这有效且看起来相同,只是长了几个字符。

var words = new[]{ "apple", "strawberry", "grape", "peach" };   
Run Code Online (Sandbox Code Playgroud)