简体   繁体   English

为什么C#多维数组没有实现IEnumerable<T> ?

[英]Why do C# multidimensional arrays not implement IEnumerable<T>?

I have just noticed that a multidimensional array in C# does not implement IEnumerable<T> , while it does implement IEnumerable .我刚刚注意到 C# 中的多维数组没有实现IEnumerable<T> ,而它实现了IEnumerable For single-dimensional arrays, both IEnumerable<T> and IEnumerable are implemented.对于一维数组,实现了IEnumerable<T>IEnumerable

Why this difference?为什么会有这种差异? If a multi-dimensional array is IEnumerable , surely it should also implement the generic version?如果多维数组是IEnumerable ,它肯定也应该实现通用版本吗? I noticed this because I tried to use an extension method on a multidimensional array, which fails unless you use Cast<T> or similar;我注意到这一点是因为我试图在多维数组上使用扩展方法,除非您使用Cast<T>或类似方法,否则该方法会失败; so I can definitely see the an argument for making multidimensional arrays implement IEnumerable<T> .所以我绝对可以看到使多维数组实现IEnumerable<T>

To clarify my question in code, I would expect the following code to print true four times, while it actually prints true , false , true , true :为了在代码中澄清我的问题,我希望以下代码打印四次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);

The CLR has two different kinds of arrays: vectors which are guaranteed to be one-dimensional with a lower bound of 0, and more general arrays which can have non-zero bounds and a rank other than 0. CLR 有两种不同类型的数组:保证是一维且下限为 0 的向量,以及可以具有非零边界和非 0 秩的更一般数组。

From section 8.9.1 of the CLI spec:来自 CLI 规范的第 8.9.1 节:

Additionally, a created vector with element type T, implements the interface System.Collections.Generic.IList<U> (§8.7), where U := T.此外,创建的元素类型为 T 的向量实现接口System.Collections.Generic.IList<U> (§8.7),其中 U := T。

I have to say it seems pretty weird to me.我不得不说这对我来说似乎很奇怪。 Given that it already implements IEnumerable I don't see why it shouldn't implement IEnumerable<T> .鉴于它已经实现了IEnumerable我不明白为什么它不应该实现IEnumerable<T> It wouldn't make as much sense to implement IList<T> , but the simple generic interface would be fine.实现IList<T>没有多大意义,但简单的通用接口就可以了。

If you want this, you could either call Cast<T> (if you're using .NET 3.5) or write your own method to iterate through the array.如果你想要这个,你可以调用Cast<T> (如果你使用 .NET 3.5)或编写你自己的方法来遍历数组。 To avoid casting you'd have to write your own method which found the lower/upper bounds of each dimension, and fetched things that way.为了避免强制转换,您必须编写自己的方法来找到每个维度的下限/上限,并以这种方式获取内容。 Not terribly pleasant.不是很愉快。

There is a workaround: you can convert any multidimensional array to an IEnumerable有一个解决方法:您可以将任何多维数组转换为 IEnumerable

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

Zero bound single dimensional arrays implements both IEnumerable and IEnumerable<T> , but multi-dimensional arrays, unfortunately, implements only IEnumerable .零边界单维数组同时实现了IEnumerableIEnumerable<T> ,但不幸的是,多维数组只实现了IEnumerable The "workaround" by @Jader Dias indeed converts a multidimensional array to IEnumerable<T> but with a huge cost: every element of an array will be boxed. @Jader Dias 的“解决方法”确实将多维数组转换为IEnumerable<T>但成本巨大:数组的每个元素都将被装箱。

Here is a version that won't cause boxing for every element:这是一个不会对每个元素造成装箱的版本:

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

Multidimensional arrays are not arrays for the purpose of the inheritance hierarchy. 多维数组不是用于继承层次结构的数组。 They're a completely separate type. 它们是完全独立的类型。 Additionally, this type has no good support from the framework for two possible reasons: 此外,由于两个可能的原因,此类型没有框架的良好支持:

  • It's not really that useful. 这不是那么有用。 The only real use for multidimensional arrays is matrices. 多维数组唯一真正的用途是矩阵。 For almost anything else, other data structures (eg jagged arrays) are better suited. 对于几乎任何其他数据,其他数据结构(例如锯齿状数组)更适合。
  • It's not trivial to devise generic, useful methods for these structures. 为这些结构设计通用的,有用的方法并非易事。

In the case of IEnumerable , how should this have been implemented, ie in which order should the elements be enumerated? IEnumerable的情况下,应该如何实现它,即枚举元素的顺序是什么? There's no order inherent in multidimensional arrays. 多维数组中没有固有的顺序。

Jagged arrays don't support IEnumerable<int> either, because multidimensional structures aren't really an array of a type, they are an array of an array of a type:锯齿状数组也不支持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);

Prints true, true, true, true.打印真,真,真,真。

Note : int[,] isn't an IEnumerable<int[]> , that's for the reasons specified in the other answer, namely there's no generic way to know which dimension to iterate over.注意int[,]不是IEnumerable<int[]> ,这是出于另一个答案中指定的原因,即没有通用的方法来知道要迭代哪个维度。 With jagged arrays, there isn't as much room for interpretation because the syntax is pretty clear about it being an array of arrays.对于锯齿状数组,没有太多解释的空间,因为语法非常清楚它是数组数组。

Think inversely.反过来想。 The 2d array already exists.二维数组已存在。 Just enumerate it.列举一下就行了。 Create a 2d array with score and place of an initial array or marks, including duplicate values.使用初始数组或标记的分数和位置创建一个二维数组,包括重复值。

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

Results:结果:

Score Place

100     1
99      2 
90      3 
50      4 
40      5 
35      6    
34      7    
31      8    
20      9     
20     10 
15     11 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM