式< T>コンパイルされますが、暗黙的にキャッシュされますか?
-
06-07-2019 - |
質問
Expression< T>
がコンパイルされると、結果のコードはフレームワークによって暗黙的にキャッシュされますか?フレームワークが暗黙的に最後のいくつかの正規表現をコンパイルしてキャッシュする静的な Regex
メソッドのラインに沿って考えています。
コンパイルされた Expression< T>
オブジェクトがキャッシュされていない 場合、コンパイル時間を抑えるためのベストプラクティスや、手動で式をキャッシュしますか?
public MyResultType DoSomething(int arg1, int arg2)
{
var result = invokeHandler(
(IDoSomethingHandler h) => h.DoSomething(arg1, arg2)
);
return result;
}
private TResult invokeHandler<T, TResult>(Expression<Func<T, TResult>> action)
where T : class
{
// Here, I might want to check to see if action is already cached.
var compiledAction = action.Compile();
var methodCallExpr = action as MethodCallExpression;
// Here, I might want to store methodCallExpr in a cache somewhere.
var handler = ServiceLocator.Current.GetInstance<T>();
var result = compiledAction(handler);
return result;
}
この例では、コンパイル済みの式をキャッシュする場合、 arg1
と arg2
の値がその時点で使用されていることを少し心配していますスタック内の適切な場所からそれらの値を取得するのではなく(つまり、現在の値を取得するのではなく)、式がコンパイルされました。
解決
いいえ。私はそうだとは思わない。キャッシュする場合は、 Delegate
参照(通常は Func&lt; ...&gt;
または Action&lt; ...&gt;
)。同様に、最高のパフォーマンスを実現したい場合は、パラメーター化された式としてコンパイルするため、呼び出すときに異なる値を送信できます。
この場合、言い直しが役立ちます:
public MyResultType DoSomething(int arg1, int arg2)
{
var result = invokeHandler(
(IDoSomethingHandler h, int a1, int a2) => h.DoSomething(a1, a2),
arg1, arg2);
return result;
}
private TResult invokeHandler<T, TResult>(Expression<Func<T,int,int,TResult>> action,
int arg1, int arg2)
where T : class
{
// Here, I might want to check to see if action is already cached.
var compiledAction = action.Compile();
var methodCallExpr = action as MethodCallExpression;
// Here, I might want to store methodCallExpr in a cache somewhere.
var handler = ServiceLocator.Current.GetInstance<T>();
var result = compiledAction(handler, arg1, arg2);
return result;
}
i.e。式の数値パラメータを作成し、(式の定数ではなく)実行時に実際のパラメータを渡します。
他のヒント
ラムダ式は自動的にキャッシュされません。そのために、独自のキャッシュ/メモ化アルゴリズムを実装する必要があります。関連するStackoverflowの質問を確認してください:
ラムダ式はC#で遅延評価されることに注意することが重要です。
所属していません StackOverflow