Вероятно, вы реализуете что-то вроде большого числа умножения или другую линейную комбинацию векторов. Причина, по которой вам нужен подход, который вы описали как встроенный делегат, вполне вероятно, из-за различного места для хранения результата во время вычисления, а также потому, что вложенные петли жестко закодированы. Поэтому я предлагаю пересмотреть код следующим образом:
public void Update(int destinationIndex, int[][] arrays, int[] indices) {
var product=1;
for(var i=indices.Length; i-->0;)
if(destinationIndex!=i)
product*=arrays[i][indices[i]];
arrays[destinationIndex][indices[destinationIndex]]+=product;
}
public void PerformUpdate(
int destinationIndex, int[] counts, int[][] arrays, Action<int, int>[] actions,
List<int> indices=null, int level=0
) {
if(level==counts.Length)
Update(destinationIndex, arrays, (indices??new List<int>()).ToArray());
else
for(int count=counts[level], i=0; i<count; i++) {
if(null!=actions&&level<actions.Length)
actions[level](i, count); // do something according to nesting level
(indices=indices??new List<int>()).Add(i);
PerformUpdate(destinationIndex, counts, arrays, actions, indices, 1+level);
indices.RemoveAt(indices.Count-1);
}
}
Этот код реализуется рекурсивным образом. int[][] array
может быть заменен на общий массив до тех пор, пока вы собираетесь определить расчет operator *
и operator +
, а скорее название методов в MutiplyScalar
и AddScalar
.
Итак, мы не будем использовать делегат Update
для управления пунктом назначения. Вместо этого мы просто используем destinationIndex
, чтобы выполнить это.Ниже приводится тестовый пример:
int[] a=new[] { 1, 2 }, b=new[] { 3, 4, 5 }, c=new[] { 6 };
Action<int, int> m=(index, count) => Debug.Print("index={0}; count={1}", index, count);
PerformUpdate(2, new[] { a.Length, b.Length, c.Length }, new[] { a, b, c }, new[] { m, m, m });
У нас есть еще инлайн делегатов там, которые называются Lambda Expressions
в C#. Согласно исходному коду, который вы указали, между вложенными for-loops есть Do something
. Однако мы не можем найти много информации, которая не известна глобально, Update
; наиболее существенной разницей, которую мы видим, является индекс итерации и конечный номер, которые являются i, I
, j, J
и k, K
. Таким образом, мы просто принимаем их как аргументы для перехода к Action<int, int>
для выполнения чего-либо, и они являются переменными для каждого уровня for-loop.
Выполнение в значительной степени зависит от indices
. Он сохраняет итерирующий индекс текущего цикла for и переходит на следующий уровень рекурсивного вызова. Кроме того, если вы передали arrays
со счетом, меньшим, чем его Length
, в indices
, он рассматривается как массив с длиной того счета, в который вы перешли. Не пропускайте отрицательный счет, ни один более крупный. Это может быть недостаток Action<int, int>
, это означало бы только ничего не делать вместо что-то делать.
Никогда, НИКОГДА не жертвуйте удобочитаемостью для производительности, если только вы не уверены в узком месте. Преждевременная оптимизация - это корень всего зла. – l46kok
Можете ли вы объяснить, что это за код? Или что такое контекст? Трудно понять, как делегаты вписываются в это ... – rae1
@ l46kok: Это не так. См. Полный текст, где эта цитата была вырезана. – abatishchev