표현식 가 컴파일되면 암시 적으로 캐시됩니까?
-
06-07-2019 - |
문제
언제 Expression<T>
컴파일 된 결과, 결과 코드는 프레임 워크에 의해 암시 적으로 캐시됩니까? 나는 정적의 선을 따라 생각하고있다 Regex
프레임 워크가 마지막 몇 개의 regexes를 암시 적으로 컴파일하고 캐시하는 방법.
컴파일 된 경우 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<...>
또는 Action<...>
). 마찬가지로, 최상의 성능을 얻으려면 매개 변수화 된 표현식으로 컴파일하므로 호출 할 때 다른 값을 보낼 수 있습니다.
이 경우 리페이스가 도움이됩니다.
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;
}
즉, 표현식의 숫자 매개 변수를 만들고 실제 런타임에 (표현에서 상수가 아닌).
다른 팁
람다 지출은 자동으로 캐시되지 않습니다. 이를 위해 자신의 캐싱/메모 화 알고리즘을 구현해야합니다. 관련 stackoverflow 질문을 확인하십시오.
Lambda 표현은 C#에서 게으른 평가를 받았다는 점에 유의해야합니다.
제휴하지 않습니다 StackOverflow