У меня есть N-мерный массив, которому я хочу иметь возможность назначить любое примитивное значение. (один тип для одного массива, но alg должен быть универсальным для всех примитивных типов).
Я написал метод, который может сделать это:
var element = Array.CreateInstance(dataType, dataDims);
foreach (var index in GetIndexes(dataDims))
{
element.SetValue(SomeKindOfValue, index);
}
Функция GetIndexes генерирует все возможные индексы для заданных измерений:
public static IEnumerable<int[]> GetIndexes(int[] dims)
{
int lastIndex = dims.Length - 1;
int lastDim = dims[lastIndex];
int[] Index = new int[dims.Length];
int currentDim = lastIndex;
while (currentDim >= 0)
{
if (currentDim == lastIndex)
{
for (int i = 0; i < lastDim; i++)
{
yield return Index;
Index[currentDim]++;
}
Index[currentDim] = 0;
currentDim--;
continue;
}
else
{
if (Index[currentDim] == dims[currentDim] - 1)
{
Index[currentDim] = 0;
currentDim--;
continue;
}
else
{
Index[currentDim]++;
currentDim = lastIndex;
continue;
}
}
}
}
ПРИМЕР: для GetIndexes (new int [] {4,2,3}) вывод будет:
0, 0, 0 |
0, 0, 1 |
0, 0, 2 |
0, 1, 0 |
0, 1, 1 |
0, 1, 2 |
1, 0, 0 |
1, 0, 1 |
1, 0, 2 |
1, 1, 0 |
1, 1, 1 |
1, 1, 2 |
2, 0, 0 |
2, 0, 1 |
2, 0, 2 |
2, 1, 0 |
2, 1, 1 |
2, 1, 2 |
3, 0, 0 |
3, 0, 1 |
3, 0, 2 |
3, 1, 0 |
3, 1, 1 |
3, 1, 2 |
Проблема в том, что присвоение значений таким способом является дорогостоящим, и этот алгоритм должен быть максимально эффективным.
Я думал, что многомерный массив на самом деле является 1d-массивом в памяти, поэтому, если бы я мог получить доступ к указателю каждого элемента, я мог бы присвоить значения без каких-либо вычислений и напрямую. Проблема в том, что мне не удалось найти способ создать указатель на универсальный класс Array (или на его первый элемент).
По сути, я пытаюсь написать общую функцию этого (которая примет любой тип примитива как тип данных массива и примет любой многомерный массив):
public static unsafe void SetElementsByPointer(int[,] array, int[] values)
{
if (values.Length != array.LongLength)
throw new Exception("array and values length mismatch.");
fixed (int* pStart = array)
{
for (int i = 0; i < array.LongLength; i++)
{
int* pElement = pStart + i;
*pElement = values[i];
}
}
}
Я буду признателен за любые другие идеи для установки значений в n-мерный массив, но путь указателя кажется наиболее эффективным, просто я не могу понять это
Заранее спасибо.