问题描述
为什么我不能将数组初始化器与隐式类型变量一起使用?
Why can't I use the array initializer with an implicitly typed variable?
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
此限制是否存在技术原因?为什么它不能像它那样推断类型:
Is there a technical reason for this limitation? Why can't it infer the type like it would for:
var number = 10;
var text = "Hello";
编译器清楚地知道我要做什么,只是不允许这样做:
The compiler clearly knows what I am trying to do, it just won't allow it:
CS0820:无法将数组初始值设定项分配给隐式类型的本地
CS0820: Cannot assign array initializer to an implicitly typed local
<小时>
更新:我使用四种合法的数组声明方法编译了一个程序,它生成了相同的 IL:http://pastebin.com/28JDAFbL
这只会增加我的困惑.并且它是这样的,因为规范是这样说的"并没有什么帮助.为什么规格是这样的?这里的理由是什么?
This just adds to my confusion. And "it is like this because the spec says so" is of little help. Why is the spec like this? What is the rationale here?
推荐答案
为什么我不能将数组初始值设定项与隐式类型变量一起使用?为什么规格是这样的?这里的理由是什么?
Why can't I use the array initializer with an implicitly typed variable? Why is the spec like this? What is the rationale here?
做出此决定时,我不在设计团队中,并且设计说明 (*) 未提及此主题.不过,我问了 2005 年做出这个决定时在场的人.
I was not on the design team when this decision was made, and the design notes(*) are silent on this subject. However, I asked someone who was in the room in 2005 when this decision was made.
解释平淡无奇.设计团队一开始就对数组初始值设定项语法非常不满意.坦率地说,数组初始值设定项不是表达式并且在语法上只能出现在本地或字段声明中,这真是太奇怪了.它使解析器复杂化.好像很奇怪
The explanation is prosaic. The design team was never very happy with the array initializer syntax in the first place. Frankly it is downright bizarre that an array initializer is not an expression and syntactically can only appear in a local or field declaration. It complicates the parser. It seems strange that
int[] x = {1};
应该是合法的,但是
M({1});
不是.
数组初始化语法也使编辑时代码分析期间的错误恢复变得复杂.假设你有类似的东西:
The array initialization syntax also makes error recovery during code analysis at edit time complicated. Suppose you have something like:
class C
{
void M()
{
{
int result = whatever();
...
}
{
int result = somethingElse();
...
}
}
}
然后您开始在编辑器中输入新声明:
and you start typing a new declaration in the editor:
void M()
{
int[] x =
{
int result = whatever();
突然间,解析器必须以一种不会混淆即将键入null;"的可怜用户的方式来处理这种情况的歧义.显然,您不打算使用代码块初始化局部变量,但是解析器完全有权说大括号只能合法地成为数组初始化程序的一部分,因此它是出乎意料的int 结果".
and suddenly now the parser has to deal with disambiguating the situation in a way that does not confuse the poor user who is about to type "null;". Clearly you do not intend to initialize the local variable with the block of code, but the parser is perfectly within its rights to say that the brace can only legally be part of an array initializer here, and therefore it is the "int result" that is unexpected.
所以,长话短说,经典"数组初始值设定项有点错误.由于向后兼容的原因,我们无法摆脱它们.但我们也不希望通过允许它们出现在更多个地方来鼓励它们的使用.
So, long story short, "classic" array initializers are a bit of a misfeature. We can't get rid of them because of backwards compatibility reasons. But we also don't want to encourage their use by allowing them in more places.
设计团队想出了在数组初始化器前加上new[]"的想法,并将that变成合法的表达式,现在问题解决了.经典数组初始值设定项的错误功能不会蔓延"到该语言的新领域,并且有一个简洁但可读的语法清楚地表明你正在这里创建一个新数组".
The design team came up with the idea of prepending "new[]" to the array initializer, and make that into a legal expression, and now the problem is solved. There is no "creep" of the classic array initializer misfeature into new areas of the language, and there is a terse but readable syntax that clearly says "you are making a new array here".
这个故事的寓意是:尝试在第一次就正确,因为语法是永恒的.
The moral of the story is: try to get it right the first time, because syntax is forever.
(*) 在我的搜索中,我确实发现了一些有趣的事情:团队最初认为var"可能不会是为该功能选择的关键字;显然它在他们身上生长.此外,一种设计要求var"局部变量不仅是隐式类型,而且是 init-once 局部变量.显然我们从来没有实现过 init-once 局部变量.
(*) In my search I did discover several interesting things: the team originally believed that "var" probably would not be the keyword chosen for the feature; apparently it grew on them. Also, one design called for "var" locals to not just be implicitly typed, but also be init-once locals. Obviously we never did implement init-once locals.
这篇关于为什么我不能将数组初始值设定项与隐式类型变量一起使用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!