1
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扁平化矩形阵列?

4

3 回答 3

3

多维数组在某种意义上是一个一维数组,它使用维度信息来访问数据,就好像它们真的存储在二维中一样。因此,当通过许多方法(例如从 class Array)和foreach迭代访问时,它被视为一维数组,因为这是内存中的实际布局。否则在迭代期间需要为每一行创建新的一维数组。

您可以尝试执行以下操作来实现您想要的:

  1. 使用锯齿状数组而不是多维一:int[][]
  2. IEnumerable<IEnumerable<T>> ByRows<T>(this T[,] array)创建将创建迭代器的扩展方法,该迭代器对行进行适当的迭代。显然,行要么是一维数组,要么是另一个自定义迭代器,它将迭代行的内容。
  3. 完全跳过foreach并使用两个嵌套for循环。
于 2013-09-05T22:46:20.967 回答
2

如果您有一个锯齿状数组,它将不会以这种方式运行(即声明为int[][]而不是的数组int[,]) Foreach 旨在枚举每个元素,并且在 2D 数组中,每个元素都是一个 int,而不是一个 int 数组(尽管静态初始化器制作看起来它不是一个数组数组)。如果你想让它按原样工作(使用二维数组),我建议使用传统的 for 循环而不是 foreach。

于 2013-09-05T22:40:50.827 回答
0

问题不在于 foreach,而在于从 GetEnumerator 返回的枚举器的实现。它所做的是将多维数组视为一个连续的值数组(这就是它在内存中的样子)。

如果您考虑如何必须实现一个枚举器以便它为您提供所需的行为,它基本上将枚举一个 IEnumerable。这实际上是一个数组数组。正如其他人所提到的,C# 用锯齿状数组或 int[][] 来表示这一点。

相反,多维数组在 C# 中建模为一块内存,您可以使用两个索引对其进行索引。你不能用一个索引来索引多维数组并返回一个数组,就像你可以使用锯齿状数组一样。事实上,如果你试图用一个索引来索引一个多维数组,你会得到一个编译错误。您可以将多维数组实现为单维数组,并自行计算将二维索引转换为单维索引。

于 2013-09-06T04:31:33.070 回答