为什么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
四次,而实际上打印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);
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[]>
,这是出于在另一个答案中指定的原因,即没有通用方法来知道迭代哪个维度。 用锯齿的数组,没有太多的解释空间,因为语法对于数组来说非常清楚。
零边界单维数组实现了IEnumerable
和IEnumerable<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