`foreach`如何遍历2D数组?

时间:2015-02-07 18:25:21

标签: c# arrays for-loop multidimensional-array foreach

我很好奇C#中的foreach循环如何遍历多维数组。在下面的代码中,第二个嵌套for循环最初是foreach,它会给出循环中放置的音高的错误位置。我知道它很难直觉它的功能,但基本上就是这样:将音高放入一个多维数组(这里,numVoices为2,exLength为10),这样你就可以得到2x10的音高数组;然后,MIDI输出设备同时播放这些音高行中的每一行。当我使用foreach然后将音高的名称放入一个字符串中以便我可以显示网格内部的哪些音高时,foreach会以“错误”的顺序显示它们(即,音高网格中的[0,3]不是字符串中打印的内容)。使用嵌套的for,此问题消失了。我尝试使用int s(下面的代码)的2D列表的较小示例重新创建它,但这次它给出了“正确”的答案。为什么呢?

            //put pitches into grid
            //numVoices = 2, exLength = 10 (10 notes long, 2 voices)
            for (int i = 0; i < numVoices; i++ )
            {
                for(int j = 0; j < exLength; j++)
                {
                    //here we generate random pitches in different octaves
                    //depending on the voice (voice 2 is in octave
                    //below voice 1, etc)
                    randnum = (random.Next(100 - (i * 13), 112 - (i * 13)));                        

                    melodyGrid[j, i] = (Pitch)randnum;

                }
            }

            for (int i = 0; i < numVoices; i++)
            {
                for (int j = 0; j < exLength; j++)
                {
                                     //this down here makes it more readable for
                                     //humans
                                     //e.g. "FSharp5" becomes "F#5"

                    noteNames += String.Format("{0, -6}", melodyGrid[j,i].ToString().Replace("Sharp", "#").Replace("Flat", "b"));

                }
                noteNames += "\r\n"; //lower voices are just separated by newlines
            }
            Console.WriteLine(noteNames);

以下代码“正确”,但是:

int[,] nums = { {1, 2, 3}, 
                            {4, 5, 6},
                            {7, 8 ,9} };
            foreach (int i in nums)
            {
                Console.Write("{0} ", i);
            }

我是否有可能只是犯了语义错误?或者foreach循环以不同的方式迭代数组?

1 个答案:

答案 0 :(得分:4)

  

我很好奇C#中的foreach循环如何遍历多维数组。

对于像这样的问题,最终的权威是C#语言规范。在本例中,第8.8.4节:

  

foreach遍历数组元素的顺序如下:对于单维数组,元素以递增的索引顺序遍历,从索引0开始,以索引Length – 1结束。对于多维数组,遍历元素,使得最右边的维度的索引首先增加,然后是下一个左维度,依此类推到左边。

现在,将其与您使用for语句进行迭代的方式进行比较:

for (int i = 0; i < numVoices; i++ )
{
    for(int j = 0; j < exLength; j++)
    {
        ...
        melodyGrid[j, i] = (Pitch)randnum;

换句话说,您首先递增最左侧的维度...所以是的,这会得到与foreach不同的结果。如果您想使用foreach但获得相同的迭代顺序,则需要切换语音和长度的索引。或者,如果你想保持相同的索引顺序,只需使用for循环并对它感到满意。