2017-11-28 3 views
1

Expressionタイプの形式でExpression<Func<...,...,...,TResult>>(ランダムであるが固定数のパラメータ)インスタンスを受け取ります。例えばパラメータが与えられた式funcの結果を計算する最速の方法

Expression<Func<int,int,int>> adderExpression = (a,b) => a+b; 
LambdaExpression receivedExpression = adderExpression; 
//Later on, I get only the receivedExpression variable and an array of values for which I have to compute: 
var values = new object[] {3, 4}; 
var result = receivedExpression.Compile().DynamicInvoke(values); 

Iがアクセスを持っている唯一のものはreceivedExpression変数とIコンパイル式を適用した結果を計算するために持っているため、オブジェクトの値の配列です。

receivedExpressionは変更されません。一度取得すれば、同じままです。

私の状況で変数resultを計算する最も速い方法は何ですか?この場合、DynamicInvokeは非常に遅いので、結果を計算するためのより速い方法があるのだろうかと思いました。

+0

何のメソッド 'コンパイルがないので、あなたのコードがコンパイルされません。あなたはExpressionで渡さを含むことラムダをコンパイル'式'の上にある。 – NetMage

+1

おそらく 'LambdaExpression receivedExpression'でしょうか? – Phaeze

+0

関連するタイプ、特に戻りタイプを知っていますか? – NetMage

答えて

1

あなたは引数配列をとり、効果的に動的に相当作成、Expressionに渡さ呼び出すためにInvokeを使用してコンパイルしたデリゲートを作成することができます

var rec = receivedExpression.Compile(); 
var f = (object[] p) => (object)rec.Invoke((type0)p[0],(type1)p[1],...); 

まず、あなたは(不明)に変換する必要があります。 receivedExpressionobjectへの戻り値の型は、あなたが強く型付けされたデリゲートを作成することができます。

var fr = Expression.Lambda(Expression.Convert(receivedExpression.Body, typeof(object)), receivedExpression.Parameters); 

は、その後、あなたは、ラムダのためExpressionを作成できますobject[]を受け取り、固定数と種類の引数を持つラムダを呼び出します。

まず、ラムダのパラメータが必要になります。そして、

var arg = Expression.Parameter(typeof(object[])); 

あなたはreceivedExpressionに渡す正しいタイプのものobject[]パラメータの各メンバーを変換する必要があります。そして、

var args = values.Select((v, i) => Expression.Convert(Expression.ArrayIndex(arg, Expression.Constant(i)), v.GetType())).ToArray(); 

新しいラムダを作成することができます:

var frs = Expression.Lambda(Expression.Invoke(fr, args), arg); 

var frsc = (Func<object[], object>)frs.Compile(); 

最後に、あなたが効率的にreceivedExpressionを呼び出すために、新たなラムダを使用することができます:

object result = frsc.Invoke(values); 
+0

いいね!これを行うためにInvokeよりも高速な方法があるのだろうかと思います。それでも、あなたのアプローチは〜709ns(DynamicInvokeを使用)から56ns(あなたのメソッドを使用して)になります。 –

+0

'Invoke'は、コンパイラが通常の関数呼び出しを' Expression'ツリーに変換する方法です。できるだけ効率的だと思います。 'Func <>'へのリテラルコールをチェックすることは、ILで 'Invoke'を使ってそれを示しています。 – NetMage

関連する問題