おそらく、多数の乗算や他のベクトルの線形結合のようなものを実装しています。インラインデリゲートとして説明したアプローチが必要になる理由は、おそらく計算中に結果を格納する場所が異なるためであり、ネストされたforループがハードコーディングされているためです。したがって、次のようにコードを修正することをお勧めします。
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#で呼び出されます。提供した元のコードによるとDo something
、ネストされたforループの間にsがあります。ただし、グローバルに知られていない情報はあまりありませんUpdate
。私たちが見ることができる最も重要な違いは、反復インデックスと終了番号、であるi, I
、j, J
とk, K
です。したがって、これらを引数として取り、Action<int, int>
何かを行うためにforに渡すだけで、forループのレベルごとに可変になります。
実行はに大きく依存しindices
ます。現在のforループの反復インデックスを格納し、次のレベルの再帰呼び出しに渡されます。さらに、 inarrays
よりも小さいカウントでを渡した場合、渡したカウントの長さの配列として扱われます。負のカウントを渡さないでください。大きいカウントも渡さないでください。不足している可能性があります。つまり、何かをする代わりに何もしないということです。Length
indices
Action<int, int>