我一直认为这两种方式都很好。然后做了这个测试并意识到重新分配不允许这样做:
int[] a = {0, 2, 4, 6, 8};
工作正常但不是:
int [ ] a;
a = { 0, 2, 4, 6, 8 };
任何技术原因?我想我会在这里问一下,因为这种行为是我直觉所期望的。
答案 0 :(得分:20)
首先,我们让条款正确。那不是集合初始化程序。这是一个数组初始值设定项。集合初始值设定项始终遵循集合类型的构造函数。数组初始值设定项仅在局部或字段声明初始值设定项或数组创建表达式中合法。
你完全正确地注意到这是一个奇怪的规则。让我准确地描述它的古怪:
假设您有一个采用一组int的方法M.所有这些都是合法的:
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!
似乎要么“孤独的”数组初始化程序应该是合法的,“装饰”的数组初始化程序应该是合法的。奇怪的是,这个伪表达只在初始化器中有效,而不是表达式合法的其他任何地方。
在我批评和捍卫这一选择之前,我想说,首先,这种差异是一次历史性事故。这没有令人信服的好理由。如果我们可以在不破坏代码的情况下摆脱它,我们会。但我们做不到。如果我们今天再次从头开始设计C#,我认为没有“new”的“孤独”数组初始化程序不是一个有效的语法。
所以,让我首先说明为什么不应该允许数组初始值设定项作为表达式,并且应该允许在局部变量初始值设定项中使用。然后我会给出相反的原因。
不应允许数组初始值设定项作为表达式的原因:
数组初始值设定项违反了{
总是意味着引入新代码块的nice属性。在您键入时解析的IDE中的错误恢复解析器喜欢使用大括号作为判断语句何时不完整的便捷方式;如果你看到:
if (x == M(
{
Q(
然后代码编辑器很容易猜到你在))
之前遗漏了{
。编辑将假设Q(
是一个陈述的开头而且它没有结束。
但是如果数组初始值设定项是合法表达式,那么可能缺少的是)})){}
跟随<{em} Q
。
其次,数组初始值设定项作为表达式违反了所有堆分配在其中具有“新”的好原则。
为什么应该在字段和本地初始值设定项中允许数组初始值设定项的原因:
请记住,在隐式类型化的本地,匿名类型或数组类型推断之前,数组初始值设定项已添加到v1.0中的语言中。在那天我们没有令人愉快的“new [] {10,20,30}”语法,所以没有数组初始值设定项,你不得不说:
int[] x = new int[] { 10, 20, 30 };
这似乎非常多余!我可以看出为什么他们想要从那里获得“new int []”。
当你说
时int[] x = { 10, 20, 30 };
它在语法上不明确;解析器知道这是一个数组初始化器而不是代码块的开头(与我上面提到的情况不同。)它也不是类型模糊的;很明显,初始化程序是来自上下文的一组int。
因此,该论证证明了为什么C#1.0中的数组初始值设定项在本地和字段初始值设定项中是允许的,而在表达式上下文中则不允许。
但那不是我们今天所处的世界。如果我们今天从头开始设计这个,我们可能没有没有“新”的数组初始化器。现在我们当然意识到更好的解决方案是:
var x = new[] { 10, 20, 30 };
并且该表达式在任何上下文中都有效。如果您认为合适,可以在=
的“声明”侧或“初始化程序”侧明确键入它,或者您可以让编译器推断出任何一方或两者的类型。
所以,总结一下,是的,你是对的,数组初始化器只能在本地和字段声明中,而不能在表达式上下文中。十年前有充分的理由,但在具有类型推理的现代世界中,它已经不再是一个很好的理由了。这只是一个历史性的意外事故。
答案 1 :(得分:1)
最重要的是:
int [] a;// ={1,2,3,4};
a = new [] {1, 2, 3, 4};
在VB中的工作方式与声明相同,更容易xD
Dim a() As Integer '={1,2,3,4}
a = {1, 2, 3, 4}