多维数组不实现IEnumerable ,还是它们呢?

由于我仍然不理解的原因( 参见这个SO问题 )CLR中的多维数组没有实现IEnumerable 。 所以以下不编译:

 var m = new int[2,2] {{1, 2}, {3, 4}}; var q = from e in m select e; 

那怎么会在VB.NET中运行得很好呢?

 Sub Main() Dim m(,) As Integer = {{1, 2}, {3, 4}} Dim q = From e In m Select e For Each i In q Console.WriteLine(i) Next End Sub 

更新:

以下代码有效,因为C#编译器将foreach替换for循环以遍历每个维度。

 foreach(var e in m) Console.WriteLine(e); 

 int[,] numArray3 = new int[,] { { 2, 2 }, { 3, 3 } }; int upperBound = numArray3.GetUpperBound(0); int num4 = numArray3.GetUpperBound(1); for (int i = numArray3.GetLowerBound(0); i <= upperBound; i++) { for (int j = numArray3.GetLowerBound(1); j <= num4; j++) { int num = numArray3[i, j]; Console.WriteLine(num); } } 

该查询在VB.Net中工作,因为它被转换为

 IEnumerable q = m.Cast().Select(o => o); 

这是有效的,因为你可以在IEnumerable上调用Cast (), [*,*]实现。

LINQ查询在C#中不起作用,因为C#和VB.Net设计者采用了不同的方法。 VB.Net采用更多的手持方法并修复您的错误并将IEnumerable转换为IEnumerable以便可以使用它。

在C#中,您可以使用来模拟它

 var q = from e in m.Cast() select e; 

他们没有在C#中原生实现它有两个原因:

  • 你可以用不止一种方法做到这一点。 你想要每个’细胞’,还是你想要每个’行’? 你如何定义’row’:[],IEnumerable,other? 如果有两个以上的尺寸怎么办? 一旦他们选择了一种方式,一大批开发人员会告诉他们他们应该以不同的方式做到这一点。
  • 感谢迭代器块和yield关键字,实现您自己的特定于您当时的需求非常容易。 当然,这是一个C#构造,但它在VB中并没有那么难。

Array的MSDN页面包括:

重要说明:在.NET Framework 2.0版中,Array类实现System.Collections.Generic.IList ,System.Collections.Generic.ICollection 和System.Collections.Generic.IEnumerable generic接口。 这些实现在运行时提供给数组,

注意引用中的最后一个单词……看起来这一代不会发生在多维数组中(所以文档错误)。

但正如其他人所指出的那样, T会是什么? 可以为T[]做一个很好的案例(或者,现在使用LINQ, IEnumerable )。

最后,如果你想迭代所有数组的成员,只需坚持使用IEnumerable和Cast 扩展名。 否则很容易自己写。

提示:使用类型化范围变量而不是Cast ()

塞缪尔说:

在C#中,您可以使用来模拟它

 var q = from e in m.Cast() select e; // q is of type IEnumerable 

就C#中模仿VB来说当然是正确的,但是你会丢失你的类型信息。 相反,它简单地声明你的范围变量,更简单,更简单易读。

以下编译,执行得更好,类型安全且不会丢失类型信息:

 var m = new int[2, 2] { { 1, 2 }, { 3, 4 } }; var q = from int e in m select e; // q is of type IEnumerable 

在最初的建议中,你将拥有一个IEnumerable ,使用int e你改成IEnumerable ,这有其优点。