为什么C#multidimensional array不能实现IEnumerable <T>?

我刚刚注意到,C#中的multidimensional array并没有实现IEnumerable<T> ,而是实现了IEnumerable 。 对于一维数组, IEnumerable<T>IEnumerable都被实现。

为什么这个区别? 如果一个multidimensional array是IEnumerable ,当然它也应该实现通用版本? 我注意到这一点,因为我试图在multidimensional array上使用扩展方法,除非使用Cast<T>或类似的方法,否则失败。 所以我可以肯定地看到使multidimensional array实现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); 

CLR有两种不同的数组: 向量保证是一维的,下限为0,更一般的数组可以有非零的边界和不等于0的秩。

从CLI规范的第8.9.1节可以看出:

另外,创build的元素types为T的vector实现了接口System.Collections.Generic.IList<U> (§8.7),其中U:= T.

我不得不说我觉得这很奇怪。 鉴于它已经实现IEnumerable我不明白为什么它不应该实现IEnumerable<T> 。 实现IList<T>没有太大的意义,但简单的通用接口将会很好。

如果你想这样做,你可以调用Cast<T> (如果你正在使用.NET 3.5)或者编写你自己的方法遍历数组。 为了避免投射,你必须编写自己的方法,find每个维度的下限/上限,并以这种方式获取事物。 不是非常愉快。

有一个解决方法:您可以将任何multidimensional array转换为IEnumerable

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

multidimensional array不是用于inheritance层次结构的数组。 他们是一个完全独立的types。 此外,这种types没有从框架得到很好的支持,原因有两个:

  • 这不是真的有用。 multidimensional array唯一真正的用途是matrix。 对于其他任何东西,其他数据结构(例如锯齿状的arrays)更适合。
  • 为这些结构devise通用的,有用的方法并不是微不足道的。

IEnumerable的情况下,应该如何实现,也就是按照哪个顺序来枚举元素呢? multidimensional array中没有固有的顺序。

Jagged数组也不支持IEnumerable<int> ,因为多维结构并不是真正的一个types数组,它们是一个types数组的数组:

 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[]> ,这是出于在另一个答案中指定的原因,即没有通用方法来知道迭代哪个维度。 用锯齿的数组,没有太多的解释空间,因为语法对于数组来说非常清楚。

零边界单维数组实现了IEnumerableIEnumerable<T> ,但不幸的是,multidimensional array只能实现IEnumerable 。 @Jader Dias的“解决方法”确实将multidimensional array转换为IEnumerable<T>但代价很大:数组中的每个元素都将被装箱。

这里是一个不会导致每个元素拳击的版本:

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

反过来思考。 2d数组已经存在。 只要列举一下。 创build一个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