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

发布于 2024-12-03 09:13:54 字数 850 浏览 4 评论 0原文

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

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

这只会增加我的困惑。而“它是这样的,因为规范是这样说的”没有什么帮助。为什么规范是这样的?这里的理由是什么?

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: Cannot assign array initializer to an implicitly typed local


Update: I compiled a program using the four legal array declaration methods, and it generates the same 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

标点 2024-12-10 09:13:54

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

当做出这个决定时,我并不在设计团队中,并且设计说明(*)没有提及这个主题。然而,我询问了 2005 年做出这一决定时在场的人。

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

int[] x = {1};

应该是合法的,但

M({1});

事实并非如此。

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

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

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

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

突然间,解析器必须以一种不会让即将输入“null;”的可怜用户感到困惑的方式来处理消除歧义的情况。显然,您不打算使用代码块初始化局部变量,但解析器完全有权利说大括号只能合法地成为此处数组初始值设定项的一部分,因此它是意外的“int 结果”。

因此,长话短说,“经典”数组初始值设定项有点错误。由于向后兼容性的原因,我们无法摆脱它们。但我们也不想通过允许它们出现在更多地方来鼓励它们的使用。

设计团队想出了在数组初始值设定项前添加“new[]”的想法,并将that变成合法的表达式,现在问题就解决了。经典数组初始值设定项错误功能不会“蔓延”到该语言的新领域,并且有一种简洁但可读的语法清楚地表明“您正在此处创建一个新数组”。

这个故事的寓意是:尝试第一次就做对,因为语法是永远的。


(*) 在我的搜索中,我确实发现了一些有趣的事情:团队最初认为“var”可能不会成为该功能选择的关键字;显然它对他们产生了影响。此外,一种设计要求“var”局部变量不仅是隐式类型的,而且还是一次性初始化的局部变量。显然我们从未实现过 init-once 局部变量。

Why can't I use the array initializer with an implicitly typed variable? Why is the spec like this? What is the rationale here?

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};

should be legal, but

M({1});

is not.

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();

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.

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.


(*) 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.

单身狗的梦 2024-12-10 09:13:54

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

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

You can use the following syntax to do this:

var words = new[] { "apple", "strawberry", "grape", "peach" };
捶死心动 2024-12-10 09:13:54

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

然而,它的工作原理和外观都是一样的,只是长了几个字符。

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

Probably because you are not giving it any type, eg. is it array, list, or some other collection.

However, this works and looks same and is just couple characters longer.

var words = new[]{ "apple", "strawberry", "grape", "peach" };   
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文