75

我刚刚注意到 C# 中的多维数组没有实现IEnumerable<T>,但它确实实现了IEnumerable。对于一维数组,两者IEnumerable<T>IEnumerable实现了。

为什么会有这种差异?如果多维数组是IEnumerable,那么它肯定也应该实现泛型版本吗?我注意到这一点是因为我尝试在多维数组上使用扩展方法,除非您使用Cast<T>或类似方法,否则该方法会失败;所以我绝对可以看到实现多维数组的论据IEnumerable<T>

为了在代码中澄清我的问题,我希望以下代码打印true四次,而它实际上打印true, false, true, true

int[] singleDimensionArray = new int[10];
int[,] multiDimensional = new int[10, 10];

Debug.WriteLine(singleDimensionArray is IEnumerable<int>);
Debug.WriteLine(multiDimensional is IEnumerable<int>);
Debug.WriteLine(singleDimensionArray is IEnumerable);
Debug.WriteLine(multiDimensional is IEnumerable);
4

5 回答 5

51

CLR 有两种不同类型的数组:保证为一维且下限为 0 的向量,以及更一般的数组,其可以具有非零边界和非 0 的秩。

从 CLI 规范的第 8.9.1 节:

此外,创建的元素类型为 T 的向量实现了接口 System.Collections.Generic.IList<U> (第 8.7 节),其中 U := T。

我不得不说这对我来说似乎很奇怪。鉴于它已经实现了,IEnumerable我不明白为什么它不应该实现IEnumerable<T>. 实现它没有多大意义IList<T>,但简单的通用接口就可以了。

如果需要,您可以调用Cast<T>(如果您使用的是 .NET 3.5)或编写自己的方法来遍历数组。为了避免强制转换,您必须编写自己的方法来找到每个维度的下限/上限,并以这种方式获取内容。不是很愉快。

于 2008-11-08T20:14:33.437 回答
18

有一个解决方法:您可以将任何多维数组转换为 IEnumerable

public static class ArrayExtensions
{
    public static IEnumerable<T> ToEnumerable<T>(this Array target)
    {
        foreach (var item in target)
            yield return (T)item;
    }
}
于 2009-07-25T21:45:42.277 回答
7

零界一维数组同时实现IEnumerableIEnumerable<T>,但不幸的是,多维数组只实现IEnumerable。@Jader Dias 的“解决方法”确实将多维数组转换为IEnumerable<T>但代价高昂:数组的每个元素都将被装箱。

这是一个不会导致每个元素装箱的版本:

public static class ArrayExtensions
{
    public static IEnumerable<T> ToEnumerable<T>(this T[,] target)
    {
        foreach (var item in target)
            yield return item;
    }
}
于 2017-10-29T06:02:58.260 回答
1

锯齿数组也不支持IEnumerable<int>,因为多维结构并不是真正的类型数组,它们是类型数组的数组:

int[] singleDimensionArray = new int[10];
int[][] multiJagged = new int[10][];

Debug.WriteLine(singleDimensionArray is IEnumerable<int>);
Debug.WriteLine(multiJagged is IEnumerable<int[]>);
Debug.WriteLine(singleDimensionArray is IEnumerable);
Debug.WriteLine(multiJagged is IEnumerable);

打印真实,真实,真实,真实。

注意int[,]不是IEnumerable<int[]>,这是由于另一个答案中指定的原因,即没有通用的方法可以知道要迭代哪个维度。对于交错数组,没有太多解释空间,因为语法很清楚它是一个数组数组。

于 2008-11-08T19:58:45.450 回答
0

反过来想。二维数组已经存在。列举一下就行了。创建一个二维数组,其中包含初始数组或标记的分数和位置,包括重复值。

int[] secondmarks = {20, 15, 31, 34, 35, 50, 40, 90, 99, 100, 20};

IEnumerable<int> finallist = secondmarks.OrderByDescending(c => c);

int[,] orderedMarks = new int[2, finallist.Count()];

Enumerable.Range(0, finallist.Count()).ToList().ForEach(k => {orderedMarks[0, k] = (int) finallist.Skip(k).Take(1).Average();
orderedMarks[1, k] = k + 1;}); 

Enumerable.Range(0, finallist.Count()).Select(m => new {Score = orderedMarks[0, m], Place = orderedMarks[1, m]}).Dump();

结果:

Score Place

100     1
99      2 
90      3 
50      4 
40      5 
35      6    
34      7    
31      8    
20      9     
20     10 
15     11 
于 2014-12-05T18:41:47.777 回答