Работает ли Array.Copy с многомерными массивами?

Этот код работает нормально:

var newArray = new Rectangle[newHeight, newWidth];

for (int x = 0; x < newWidth; x++)
    for (int y = 0; y < newHeight; y++)
        newArray[y, x] = (x >= width) || (y >= height) ? Rectangle.Empty : tiles[y, x];

Но мне не очень повезло заменить его на Array.Copy. По сути, если массив с измененным размером больше, он просто добавляет к краям пустые прямоугольники. Если он меньше, то следует просто обрезать края.

При этом:

Array.Copy(tiles, newArray, newWidth * newHeight);

Он портит массив, и все его содержимое становится беспорядочным и не сохраняет свой первоначальный индекс. Может, у меня просто мозги кипятятся или что-то в этом роде?


person Andrew Godfrey    schedule 01.09.2011    source источник


Ответы (4)


Да. Однако это не работает так, как вы думаете. Скорее, он думает о каждом многомерном массиве как об одномерном массиве (что на самом деле является тем, чем они являются в памяти, это просто уловка, которая позволяет нам поместить некоторую структуру поверх них, чтобы думать о них как о многомерных), а затем копирует единственный -габаритные конструкции. Итак, если у вас есть

1 2 3
4 5 6

и хотите скопировать его в

x x x x
x x x x

тогда он будет думать о первом массиве как

1 2 3 4 5 6

а второй как

x x x x x x x x

и результат будет

1 2 3 4 5 6 x x

который покажется вам

1 2 3 4
5 6 x x

Понятно?

person jason    schedule 01.09.2011
comment
Вау, спасибо. Наконец-то я понял, как им пользоваться. Все это время я никогда не думал, что это сработает для многомерных массивов. - person Martheen; 01.09.2011
comment
Я понимаю, но можно ли как-то это исправить, чтобы он нормально работал? - person Andrew Godfrey; 01.09.2011
comment
Я полностью за повторное использование кода, но есть ли конкретная причина, по которой вы хотите заменить свои рабочие 3 строки кода? - person Paul Walls; 01.09.2011
comment
@ Эндрю Годфри: он работает правильно; это просто не работает так, как вы думаете, что это должно работать. Нет способа заставить его работать так, как вы думаете, он должен работать. Array.Copy должен быть молниеносно быстрым, а это означает использование того факта, что копирование линейно-непрерывных фрагментов памяти происходит молниеносно. Вы просите скопировать таким образом, чтобы это не было линейно-непрерывным. Array.Copy не предназначался для этой работы. Вы должны найти что-то еще, что сделает это за вас. В частности, код, который вы уже написали, делает именно то, что вы хотите. Используй это. - person jason; 01.09.2011
comment
Хорошо, спасибо! Мне просто интересно, потому что моя программа готова, и я просто рефакторинг прямо сейчас, чтобы она выглядела красиво O_O - person Andrew Godfrey; 01.09.2011
comment
Имейте в виду, что хотя Array.Copy не требует, чтобы его исходный и целевой массивы были одинаковой длины в каждом измерении, он требует, чтобы оба они имели одинаковый ранг (количество измерений). Buffer.BlockCopy не имеет этого ограничения. - person rwong; 15.03.2014

Я использую этот код:

public static void ResizeBidimArrayWithElements<T>(ref T[,] original, int rows, int cols)
{

    T[,] newArray = new T[rows, cols];
    int minX = Math.Min(original.GetLength(0), newArray.GetLength(0));
    int minY = Math.Min(original.GetLength(1), newArray.GetLength(1));

    for (int i = 0; i < minX; ++i)
        Array.Copy(original, i * original.GetLength(1), newArray, i * newArray.GetLength(1), minY);

    original = newArray;

}

такой вызов для массива строк

ResizeBidimArrayWithElements<string>(ref arrayOrigin, vNumRows, vNumCols);
person Biggum    schedule 08.05.2013

У меня была потребность потреблять данные из буфера и копировать их в большой массив хранения до следующего прерывания. Копирование в цикле не было вариантом; слишком медленно. Мне не нужна была многомерная структура объединенных данных, пока не было выполнено все копирование, это означало, что я мог Buffer.BlockCopy() в одномерный массив, затем снова скопируйте в многомерный массив, чтобы получить требуемую структуру. Вот некоторый код (запустите его в консоли), который продемонстрирует технику, а также производительность.

static class Program
{
    [STAThread]
    static void Main()
    {
        Stopwatch watch = new Stopwatch();

        const int width = 2;
        const int depth = 10 * 1000000;

        //  Create a large array of data
        Random r = new Random(100);
        int[,] data = new int[width, depth];
        for(int i = 0; i < width; i++)
        {
            for(int j = 0; j < depth; j++)
            {
                data[i, j] = r.Next();
            }
        }

        //  Block copy to a single dimension array
        watch.Start();
        int[] buffer = new int[width * depth];
        Buffer.BlockCopy(data, 0, buffer, 0, data.Length * sizeof(int));
        watch.Stop();
        Console.WriteLine("BlockCopy to flat array took {0}", watch.ElapsedMilliseconds);

        //  Block copy to multidimensional array
        int[,] data2 = new int[width, depth];
        watch.Start();
        Buffer.BlockCopy(buffer, 0, data2, 0,buffer.Length * sizeof(int));
        watch.Stop();
        Console.WriteLine("BlockCopy to 2 dimensional array took {0}", watch.ElapsedMilliseconds);


        //  Now try a loop based copy - eck!
        data2 = new int[width, depth];
        watch.Start();
        for (int i = 0; i < width; i++)
        {
            for (int j = 0; j < depth; j++)
            {
                data2[i, j] = data[i, j];
            }
        }
        watch.Stop();
        Console.WriteLine("Loop-copy to 2 dimensional array took {0} ms", watch.ElapsedMilliseconds);
    }
}

Выход:

BlockCopy to flat array took 14 ms
BlockCopy to 2 dimensional array took 28 ms
Loop-copy to 2 dimensional array took 149 ms
person scubasteve    schedule 09.10.2015

Просто используйте функцию «Clone()», как показано ниже:

Это ваш список массивов

object newArray = new object [row, column];

При создании другого массива просто используйте этот код:

object[,] clonedArray = (object[,]) newArray.Clone();

Простой! Веселиться!

person Gláucio Leonardo Sant'ana    schedule 17.05.2018