在C#中索引到任意等级的数组

时间:2010-08-04 18:35:14

标签: c# arrays iteration padding pinning

我需要遍历任意排名的数组。这适用于阅读和写作,因此GetEnumerator将无效。

Array.SetValue(object, int)不适用于多维数组。 Array.SetValue(object, params int[])需要过多的算术来迭代多维空间。它还需要动态调用来绕过签名的params部分。

我很想固定数组并用指针迭代它,但我找不到任何文档说多维数组保证是连续的。如果他们在维度的末尾有填充,那么这将无效。我也更愿意避免不安全的代码。

是否有一种简单的方法可以仅使用单个索引顺序寻址多维数组?

3 个答案:

答案 0 :(得分:5)

保证多维数组是连续的。来自ECMA-335:

  

数组元素应按行主要顺序排列在数组对象中(即,与最右边的数组维度相关联的元素应从最低到最高的索引连续布局。)

这样可行:

int[,,,] array = new int[10, 10, 10, 10];

fixed (int* ptr = array)
{
    ptr[10] = 42;
}

int result = array[0, 0, 1, 0];  // == 42

答案 1 :(得分:1)

您可以使用RankGetUpperBound属性/方法创建一个可以传递给数组的SetValueGetValue方法的索引数组:

int[] Indices(Array a, int idx)
{
    var indices = new int[a.Rank];

    for (var i = 0; i < a.Rank; i++)
    {
        var div = 1;

        for (var j = i + 1; j < a.Rank; j++)
        {
            div *= a.GetLength(j);
        }

        indices[i] = a.GetLowerBound(i) + idx / div % a.GetLength(i);
    }

    return indices;
}

..并像这样使用它:

for (var i = 0; i < array.Length; i++)
{
    var indices = Indices(array, i);
    array.SetValue(i, indices);
    var val = array.GetValue(indices);
}

答案 2 :(得分:-1)

也许你可以将它们全部加入到一个临时集合中,然后迭代它。