是否有可能防止foreach扁平化矩形阵列?

时间:2013-09-05 22:34:49

标签: c#

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展平矩形阵列?

3 个答案:

答案 0 :(得分:3)

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

您可以尝试按照以下方式实现目标:

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

答案 1 :(得分:2)

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

答案 2 :(得分:0)

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

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

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