是否可以防止 foreach 展平矩形数组
本文关键字:数组 foreach 是否 | 更新日期: 2023-09-27 18:30:16
using System;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
int[,] x = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 }, { 10, 11, 12 } };
foreach (var i in x)
{
foreach (var j in i)
{
Console.WriteLine(j);
}
}
}
}
}
我注意到var i in x
展平数组,因此它会为第二个foreach
生成以下错误。
错误 1 foreach 语句无法对类型为"int"的变量进行操作 因为"int"不包含"GetEnumerator"的公共定义
是否可以防止foreach
扁平化矩形阵列?
从某种意义上说,多维数组是一个一维数组,它使用维度信息来访问数据,就好像它们真的存储在二维中一样。正因为如此,当通过许多方法(例如从类Array
)访问时,foreach
迭代,它被视为一维数组,因为这是内存中的实际布局。否则,在迭代期间,需要为每一行创建新的一维数组。
您可以尝试执行以下操作来实现您想要的:
- 使用交错数组而不是多维数组:
int[][]
. - 创建扩展方法
IEnumerable<IEnumerable<T>> ByRows<T>(this T[,] array)
,该方法将创建对行执行正确迭代的迭代器。显然,行要么是一维数组,要么是另一个迭代行内容的自定义迭代器。 - 完全跳过
foreach
并使用两个嵌套for
循环。
有一个交错数组,它就不会以这种方式运行(即声明为int[][]
而不是int[,]
的数组) Foreach 旨在枚举每个元素,在 2D 数组中,每个元素都是 int,而不是 int 数组(尽管静态初始值设定项使其看起来像是数组数组,但事实并非如此)。如果你想让它按原样工作(使用 2D 数组),我建议使用传统的 for 循环而不是 foreach。
问题不在于foreach,而在于从GetEnumerator返回的枚举器的实现。它所做的是将多维数组视为一个连续的值数组(这就是它在内存中的内容)。
如果您考虑如何实现枚举器,以便它为您提供所需的行为,那么它基本上是通过 IEnumerable 进行枚举。这实际上是一个数组数组。C# 用交错数组或 int[][] 表示这一点,正如其他人所提到的。
相反,多维数组在 C# 中建模为使用两个索引编制索引的内存块。您不能像使用交错数组那样,用一个索引索引多维数组并返回一个数组。实际上,如果您尝试使用一个索引为多维数组编制索引,则会出现编译错误。您可以将多维数组实现为单维数组,并自己进行数学运算以将二维索引转换为单维索引。