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

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

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

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

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

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

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

 int[] x = {1}; 

应该是合法的,但是

 M({1}); 

不是。

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

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

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

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

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

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

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

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


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

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

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

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

但是,它的工作原理和外观相同,只是几个字符更长。

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