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