为什么在重新分配集合初始化不允许? [英] Why are collection initializers on re-assignments not allowed?

查看:242
本文介绍了为什么在重新分配集合初始化不允许?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直认为它的罚款两种方式。然后,做了这个测试,并意识到它不是重新分配允许的:

I always thought it worked fine both ways. Then did this test and realized it's not allowed on re-assignments:

int[] a = {0, 2, 4, 6, 8};

工作正常,但不是:

works fine but not:

int [ ] a;
a = { 0, 2, 4, 6, 8 };

任何技术原因?我想我会问它在这里,是因为这种行为是我所期望的直觉。

Any technical reason for this? I thought I would ask about it here, because this behavior was what I expected intuitively.

推荐答案

首先,让我们的条件是正确的。这不是一个的集合的初始化。这是一个的数组初始化的。一个集合初始化始终遵循一个构造函数集合类型。数组初始化是唯一合法的本地或外地声明初始化或数组创建EX pression。

First off, let's get the terms correct. That's not a collection initializer. That's an array initializer. A collection initializer always follows a constructor for a collection type. An array initializer is only legal in a local or field declaration initializer, or in an array creation expression.

您是完全正确地指出,这是一个奇怪的规则。让我来描述其古怪precisely:

You are completely correct to note that this is an odd rule. Let me characterize its weirdness precisely:

假设你有一个方法M.这需要int数组。所有这些都是合法的:

Suppose you have a method M that takes an array of ints. All these are legal:

int[] x = new[] { 10, 20, 30 };
int[] y = new int[] { 10, 20, 30 };
int[] z = new int[3] { 10, 20, 30 };
M(new[] { 10, 20, 30 });
M(new int[] { 10, 20, 30 });
M(new int[3] { 10, 20, 30 });

int[] q = {10, 20, 30}; // legal!
M( { 10, 20, 30 } ); // illegal!

好像无论是孤独数组初始化程序应该是合法的无处不在的装饰一个是,还是不通。这很奇怪,有这种伪EX pression这是只适用于一个初始化,而不是其他任何地方,一个前pression是合法的。

It seems like either the "lone" array initializer ought to be legal everywhere that the "decorated" one is, or nowhere. It's weird that there is this pseudo-expression that is valid only in an initializer, not anywhere else that an expression is legal.

在我既批评和捍卫这个选择,我想说的是,首先,这种差异是历史的偶然。有没有令人信服的理由吧。如果我们能够摆脱它没有打破code,我们会的。但是,我们不能。要是我们在设计C#从头今天我觉得赔率是很好的,如果没有孤独数组初始化新将不会是一个有效的语法。

Before I both criticize and defend this choice, I want to say that first and foremost, this discrepancy is a historical accident. There's no compellingly good reason for it. If we could get rid of it without breaking code, we would. But we can't. Were we designing C# from scratch again today I think odds are good that the "lone" array initializer without "new" would not be a valid syntax.

所以,让我先给出一些理由数组初始化不应该被允许作为EX pressions,应在局部变量初始化被允许。然后,我给一些原因相反。

So, let me first give some reasons why array initializers should NOT be allowed as expressions and should be allowed in local variable initializers. Then I'll give some reasons for the opposite.

原因数组初始化不应该被允许作为EX pressions:

Reasons why array initializers should not be allowed as expressions:

数组初始化违反了不错的属性, {总是意味着引进code一个新的块。在分析你的打字喜欢用大括号作为一种方便的方式告诉当一个声明是不完整的IDE中的错误恢复解析器;如果你看到:

Array initializers violate the nice property that { always means introduction of a new block of code. The error-recovery parser in the IDE that parses as you are typing likes to use braces as a convenient way to tell when a statement is incomplete; if you see:

if (x == M(
{ 
   Q(

然后是pretty的容易为code编辑猜测,你缺少)) {。编辑器将假设 Q(是一个语句的开始,它缺少结束。

Then it is pretty easy for the code editor to guess that you are missing )) before the {. the editor will assume that Q( is the beginning of a statement and it is missing its end.

但是,如果数组的初始化是合法EX pressions那么它可能是现在缺少的是)})){} 下面的在问:

But if array initializers are legal expressions then it could be that what is missing is )})){} following the Q.

二,数组初始化为EX pressions违反了很好的原则,所有的堆分配有新,在他们的地方。

Second, array initializers as expressions violate the nice principle that all heap allocations have "new" in them somewhere.

原因数组的初始化应该在外地和本地初始化被允许:

Reasons why array initializers should be allowed in field and local initializers:

记住数组的初始化已添加到V1.0的语言,之前隐式类型的当地人,匿名类型,或类型推断的数组。早在一天,我们没有足够的愉快的新的[] {10,20,30}语法,所以没有初始化数组,你不得不说:

Remember that array initializers were added to the language in v1.0, before implicitly typed locals, anonymous types, or type inference on arrays. Back in the day we did not have the pleasant "new[] { 10, 20, 30}" syntax, so without array initializers you'd have to say:

int[] x = new int[] { 10, 20, 30 };

这似乎很多余的!我能明白为什么他们要拿到新INT []救出来。

which seems very redundant! I can see why they wanted to get that "new int[]" out of there.

当你说

int[] x = { 10, 20, 30 };

它在语法上不模糊的;解析器知道,这是一个数组初始化,而不是一个code块的开始(不像情况下,我上面提到的)也不是输入歧义;很显然,初始值是整数的从上下文阵列

it is not syntactically ambiguous; the parser knows that this is an array initializer and not the beginning of a code block (unlike the case I mentioned above.) Nor is it type-ambiguous; it is clear that the initializer is an array of ints from the context.

这样的说法证明为什么在C#1.0数组初始化本地和外地初始化,但不是在EX pression背景下被允许。

So that argument justifies why in C# 1.0 array initializers were allowed in local and field initializers but not in expression contexts.

但是,这不是世界我们在今天。要是我们设计这个从头开始我们今天也许就不会没有新的数组初始化。现在我们当然意识到了更好的解决方案是:

But that's not the world we're in today. Were we designing this from scratch today we probably would not have array initializers that do not have "new". Nowadays of course we realize that the better solution is:

var x = new[] { 10, 20, 30 };

和前pression是在任何情况下有效。您可以在任意一个宣言的一面或的初始化方明确地键入了 = 如果你认为合适,也可以让编译器推断类型或者侧或两者。

and that expression is valid in any context. You can explicitly type it on either the "declaration" side or the "initializer" side of the = if you see fit, or you can let the compiler infer the types of either side or both.

所以,总结起来,是的,你是对的,这是不一致的数组初始化只能在本地和外地的声明,但不是在EX pression环境。有一个很好的理由,十年前,但在现代世界与类型推断,不再有太大的很好的理由。这只是历史的偶然,在这一点上。

So, summing up, yes, you are right that it is inconsistent that array initializers can be only in local and field declarations but not in expression contexts. There was a good reason for that ten years ago, but in the modern world with type inference, there's no longer much of a good reason for it. It's just a historical accident at this point.

这篇关于为什么在重新分配集合初始化不允许?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆