为什么c#多维数组不实现IEnumerable = T>?

时间:2022-02-19 21:33:41

I have just noticed that a multidimensional array in C# does not implement IEnumerable<T>, while it does implement IEnumerable. For single-dimensional arrays, both IEnumerable<T> and IEnumerable are implemented.

我刚刚注意到c#中的多维数组没有实现IEnumerable ,但是它实现了IEnumerable。对于单维数组,实现了IEnumerable 和IEnumerable。

Why this difference? If a multi-dimensional array is IEnumerable, surely it should also implement the generic version? I noticed this because I tried to use an extension method on a multidimensional array, which fails unless you use Cast<T> or similar; so I can definitely see the an argument for making multidimensional arrays implement IEnumerable<T>.

为什么这种差异呢?如果多维数组是IEnumerable,那么它当然也应该实现泛型版本吗?我之所以注意到这一点,是因为我试图在多维数组上使用扩展方法,除非您使用Cast 或类似的方法;因此,我可以肯定地看到让多维数组实现IEnumerable 的参数。

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,而实际上它打印的是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);

6 个解决方案

#1


41  

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的向量,实现了interface system . collection . 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>. It wouldn't make as much sense to implement IList<T>, but the simple generic interface would be fine.

我得说我觉得这很奇怪。既然它已经实现了IEnumerable,我不明白为什么它不能实现IEnumerable 。实现IList 没有多大意义,但是简单的通用接口就可以了。

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. 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.

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

#2


14  

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;
    }
}

#3


5  

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 (e.g. 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, i.e. in which order should the elements be enumerated? There's no order inherent in multidimensional arrays.

在IEnumerable中,应该如何实现这一点,即元素按什么顺序排列?多维数组没有内在的顺序。

#4


1  

Zero bound single dimensional arrays implements both IEnumerable and IEnumerable<T>, but multi-dimensional arrays, unfortunately, implements only 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.

零绑定单维数组实现了IEnumerable和IEnumerable ,但是多维数组不幸的是只实现了IEnumerable。@Jader Dias的“工作区”确实将多维数组转换为IEnumerable ,但代价是巨大的:数组的每个元素都将被装箱。

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;
    }
}

#5


0  

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. With jagged arrays, there isn't as much room for interpretation because the syntax is pretty clear about it being an array of arrays.

注意:int[,]不是IEnumerable ,这是由于其他答案中指定的原因,也就是说,没有通用的方法来知道要遍历哪个维度。对于交错数组,解释的空间并不多,因为它的语法非常清楚,它是数组的数组。 []>

#6


0  

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.

反向思考。2d数组已经存在。只是列举。创建一个带有分数和初始数组或标记位置的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();

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 

#1


41  

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的向量,实现了interface system . collection . 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>. It wouldn't make as much sense to implement IList<T>, but the simple generic interface would be fine.

我得说我觉得这很奇怪。既然它已经实现了IEnumerable,我不明白为什么它不能实现IEnumerable 。实现IList 没有多大意义,但是简单的通用接口就可以了。

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. 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.

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

#2


14  

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;
    }
}

#3


5  

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 (e.g. 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, i.e. in which order should the elements be enumerated? There's no order inherent in multidimensional arrays.

在IEnumerable中,应该如何实现这一点,即元素按什么顺序排列?多维数组没有内在的顺序。

#4


1  

Zero bound single dimensional arrays implements both IEnumerable and IEnumerable<T>, but multi-dimensional arrays, unfortunately, implements only 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.

零绑定单维数组实现了IEnumerable和IEnumerable ,但是多维数组不幸的是只实现了IEnumerable。@Jader Dias的“工作区”确实将多维数组转换为IEnumerable ,但代价是巨大的:数组的每个元素都将被装箱。

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;
    }
}

#5


0  

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. With jagged arrays, there isn't as much room for interpretation because the syntax is pretty clear about it being an array of arrays.

注意:int[,]不是IEnumerable ,这是由于其他答案中指定的原因,也就是说,没有通用的方法来知道要遍历哪个维度。对于交错数组,解释的空间并不多,因为它的语法非常清楚,它是数组的数组。 []>

#6


0  

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.

反向思考。2d数组已经存在。只是列举。创建一个带有分数和初始数组或标记位置的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();

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