Я пробовал следующее, но он просто возвращает испорченный массив.
T[,] ResizeArray<T>(T[,] original, int rows, int cols)
{
var newArray = new T[rows,cols];
Array.Copy(original, newArray, original.Length);
return newArray;
}
Спасибо, Томас, ваше объяснение было очень полезным, но реализованное вами решение слишком медленное. Я изменил его, чтобы использовать Array.Copy.
void ResizeArray<T>(ref T[,] original, int newCoNum, int newRoNum)
{
var newArray = new T[newCoNum,newRoNum];
int columnCount = original.GetLength(1);
int columnCount2 = newRoNum;
int columns = original.GetUpperBound(0);
for (int co = 0; co <= columns; co++)
Array.Copy(original, co * columnCount, newArray, co * columnCount2, columnCount);
original = newArray;
}
Здесь я предполагаю, что строк больше, чем столбцов, поэтому я структурировал массив как [столбцы, строки]. Таким образом, я использую Array.Copy для всего столбца за один снимок (намного быстрее, чем одна ячейка за раз).
Он работает только для увеличения размера массива, но его также можно изменить, чтобы уменьшить размер.
Большинство методов в классе массива работают только с одномерными массивами, поэтому вы должны выполнить копирование вручную:
T[,] ResizeArray<T>(T[,] original, int rows, int cols)
{
var newArray = new T[rows,cols];
int minRows = Math.Min(rows, original.GetLength(0));
int minCols = Math.Min(cols, original.GetLength(1));
for(int i = 0; i < minRows; i++)
for(int j = 0; j < minCols; j++)
newArray[i, j] = original[i, j];
return newArray;
}
Чтобы понять, почему это не работает с Array.Copy
, вам нужно рассмотреть расположение многомерного массива в памяти. Элементы массива не на самом деле хранятся в виде двумерного массива, они хранятся непрерывно, строка за строкой. Итак, этот массив:
{ { 1, 2, 3 },
{ 4, 5, 6 } }
на самом деле устроен в памяти так: { 1, 2, 3, 4, 5, 6 }
Теперь предположим, что вы хотите добавить еще одну строку и еще один столбец, чтобы массив выглядел вот так:
{ { 1, 2, 3, 0 },
{ 4, 5, 6, 0 },
{ 0, 0, 0, 0 } }
Теперь расположение в памяти будет следующим: { 1, 2, 3, 0, 4, 5, 6, 0, 0, 0, 0, 0 }
Но Array.Copy
рассматривает все массивы как одномерные. MSDN говорит:
При копировании между многомерными массивами массив ведет себя как длинный одномерный массив, в котором строки (или столбцы) концептуально заложены в конец
Поэтому, когда вы пытаетесь скопировать исходный массив в новый, он просто копирует одну ячейку памяти в другую, что дает в одномерном представлении:
{ 1, 2, 3, 4, 5, 6, 0, 0, 0, 0, 0, 0 }
.
Если вы преобразуете это в двумерное представление, вы получите следующее:
{ { 1, 2, 3, 4 },
{ 5, 6, 0, 0 },
{ 0, 0, 0, 0 } }
Вот почему вы получаете испорченный массив ... Обратите внимание, что это будет работать свойство, если вы изменилось количество строк, но не количество столбцов.
Это объединяет ответы Томаса и Мануэля и обеспечивает выигрыш в производительности Array.Copy и возможность увеличивать и уменьшать размер массива.
protected T[,] ResizeArray<T>(T[,] original, int x, int y)
{
T[,] newArray = new T[x, y];
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 < minY; ++i)
Array.Copy(original, i * original.GetLength(0), newArray, i * newArray.GetLength(0), minX);
return newArray;
}
Обратите внимание , что оси x и y вашего массива соответствуют вашей собственной реализации, и вам может потребоваться переключить 0 и 1 для достижения желаемого эффекта.