为什么 C # 多维数组不实现 IEnumable < T > ?

我刚才注意到,C # 中的多维数组不实现 IEnumerable<T>,而实现 IEnumerable。对于单维数组,同时实现了 IEnumerable<T>IEnumerable

为什么会这样?如果一个多维数组是 IEnumerable,那么它肯定也应该实现通用版本?我之所以注意到这一点,是因为我试图在多维数组上使用扩展方法,除非您使用 Cast<T>或类似的方法,否则这种方法会失败; 所以我可以肯定地看到使多维数组实现 IEnumerable<T>的参数。

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

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);
27091 次浏览

锯齿数组也不支持 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[]>,这是由于另一个答案中指定的原因,即没有通用的方法知道要遍历哪个维度。对于参差不齐的数组,没有太多的解释空间,因为语法非常清楚它是一个数组数组。

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)或编写自己的方法来遍历数组。为了避免强制转换,您必须编写自己的方法,找到每个维度的上下界,并以这种方式获取内容。不怎么愉快。

有一个变通方法: 您可以将任何多维数组转换为 IEnumable

public static class ArrayExtensions
{
public static IEnumerable<T> ToEnumerable<T>(this Array target)
{
foreach (var item in target)
yield return (T)item;
}
}

反向思考。二维数组已经存在。只要列举出来。创建一个包含初始数组或标记(包括重复值)的得分和位置的2d 数组。

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

零限制的单维数组同时实现了 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;
}
}