多维数组不实现IEnumerable <t>,还是实现?</t>

时间:2009-04-06 15:06:44

标签: c# vb.net arrays clr

由于我仍然不理解的原因(see this SO question)CLR中的多维数组没有实现IEnumerable<T>。所以以下内容无法编译:

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

4 个答案:

答案 0 :(得分:8)

该查询在VB.Net中有效,因为它转换为

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

这是有效的,因为您可以在Cast<TResult> IEnumerable上调用[*,*]()。

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

在C#中,您可以使用

进行模拟
var q = from e in m.Cast<object>() select e;

答案 1 :(得分:4)

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

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

答案 2 :(得分:2)

MSDN page for Array包括:

  

重要提示:   在.NET Framework 2.0版中,Array类实现System.Collections.Generic.IList&lt; T&gt;,System.Collections.Generic.ICollection&lt; T&gt;和System.Collections.Generic.IEnumerable&lt; T&gt;通用接口。这些实现在运行时提供给数组,

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

但正如其他人所说,T会是什么?可以为T[](或者,现在使用LINQ,IEnumerable<T>)提供一个很好的案例。

最后,如果你想迭代所有数组的成员,只需坚持IEnumerable和Cast&lt; T&gt;延期。否则很容易写自己的。

答案 3 :(得分:2)

提示:使用类型化范围变量

代替Cast&lt; object&gt;()


塞缪尔说:

  

在C#中,您可以使用

进行模拟
var q = from e in m.Cast<object>() select e;
// q is of type IEnumerable<object>

当然,就在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<int>

在原始建议中,您将拥有IEnumerable<object>,使用int e将其更改为IEnumerable<int>,这有其优势。