【问题标题】:Is it possible to prevent foreach from flattening rectangular arrays?是否可以防止 foreach 展平矩形阵列?
【发布时间】:2013-09-09 22:04:06
【问题描述】:
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 扁平化矩形阵列?

【问题讨论】:

  • 看起来你正在寻找一个锯齿状数组,而不是一个多维数组:int[][] x = new int[][] { new[] { 1, 2, 3 }, new[]{ 4, 5, 6 }, new[]{ 7, 8, 9 }, new[]{ 10, 11, 12 } };

标签: c#


【解决方案1】:

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

【讨论】:

    【解决方案2】:

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

    你可以尝试做以下事情来实现你想要的:

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

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-10-07
        • 2011-05-31
        • 1970-01-01
        • 2017-10-17
        • 2015-10-30
        • 2021-04-10
        • 2021-07-19
        • 2014-09-29
        相关资源
        最近更新 更多