【问题标题】:Why do I need "new" for jagged array initialization?为什么锯齿状数组初始化需要“新”?
【发布时间】:2018-02-13 21:00:42
【问题描述】:

过去我使用完整的初始化语法来初始化数组:

int[] arr = new int[1] { 1 };

但是一旦我发现我不需要在初始化期间指定类型,我就停止这样做了:

int[] arr = { 1 };

我最近再次查看了锯齿状数组,发现这种语法有一个非常特殊的问题:

int[][] jag = { { 1, 2 }, { 3 } };

上面的代码无效,这让我很困惑。此外,这种语法很好:

int[][] jag = { new []{ 1, 2 }, new []{ 3 } };

显然,这里唯一的区别是“new”关键字。通常,在其他语言中,“new”关键字表示变量将成为引用类型,但在 C# 中,数组始终是引用类型,因此实际上没有必要为数组指定“new”。有谁知道为什么我需要在这个锯齿状数组初始化中指定它?这是一个错误,还是只是一个未实现的编译器功能?

【问题讨论】:

  • 但在 C# 中,数组始终是引用类型,因此确实没有必要为数组指定“新” 这不符合。这不是一个错误,它只是不是他们内置在语言中的一点编译器糖。将来可能会或可能不会添加它。您可以尝试在 GitHub 上请求它,但由于锯齿状数组(根据我的经验)很少见,我怀疑有多少行动......
  • "new" 并不表示类型是引用类型。由于这是错误的,因此您基于此错误前提得出的任何结论都不符合逻辑。 int x = new int(); 是一种完全合法的,虽然很奇怪,写int x = 0; 的方式。 new 表示正在分配新的存储空间。对于值类型,该存储是从临时池中分配出来的,然后复制,对于引用类型,该存储是从长期池中分配出来的。
  • 另一个原因是嵌套大括号语法{ { ... }, { ... }, ... } 是为IList 类型调用.Add 的语法糖。 System.Array 没有 Add - 以及“本机”多维数组:docs.microsoft.com/en-us/dotnet/csharp/programming-guide/arrays/…
  • 请注意,如果 C# 编译器和 jitter 能够证明这样做是安全的,则允许它们复制省略。比如你有S s = new S(123);对应一个值类型S,规范的要求是分配新的存储,把新的存储传递给构造函数,构造函数运行,然后值类型被复制值s练习:在什么情况下编译器可以合法地将s的存储传递给构造函数并跳过alloc-and-copy?什么情况下不能?
  • @Will: 没有故意的打击。我只是在陈述事实。全文本交流中存在一种偏见,这使得事实陈述听起来像是批评,但它们只是事实。

标签: c# arrays jagged-arrays


【解决方案1】:

这是一个错误吗?

没有。

有人知道为什么我需要在这个锯齿状数组初始化中指定它吗?

C# 语言必须仅允许矩形多维数组使用数组初始值设定项语法,而不允许锯齿状多维数组使用,这没有根本的理论原因。

您想要的功能不存在,因为没有人设计、指定、实施、测试、记录和发布该功能。这是因为与您可以花时间研究的几乎任何其他可能的功能相比,该功能可以合理地被描述为非常非常不重要。功能很昂贵;设计团队试图将时间花在解决实际用户问题的功能上。

像您建议的那样的小“糖”功能确实得到了实施;例如,表达式体方法。但是几乎每个程序都包含小方法。绝大多数程序甚至不包含一个锯齿状的、初始化一次的数组,所以这个特性几乎不会节省半打的击键。不值得。

也许只是一个未实现的编译器功能,将在未来的 C# 版本中修复?

如果此功能对您很重要,那么设计和实现过程是开放的。随意提出、设计、指定、实施、测试和记录该功能,看看他们是否接受您的拉取请求。

【讨论】:

  • 这是我一直在寻找的答案,谢谢。考虑到上述 cmets 的严酷性质,我似乎冒犯了一些人;对于那个很抱歉。我的措辞本来可以更好——我不太关心这句语法糖,我只是好奇为什么它不存在。我怀疑这可能是原因。
  • @Darkhydro:没有冒犯或有意冒犯。全文本交流中存在一种偏见,当事实陈述只是对事实的陈述时,它们会使事实陈述听起来像批评。
猜你喜欢
  • 2010-12-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-09
  • 2019-06-17
  • 2014-05-03
  • 2011-08-21
  • 1970-01-01
相关资源
最近更新 更多