Когда выражение<T> компилируется, кэшируется ли оно неявно?

StackOverflow https://stackoverflow.com/questions/258864

Вопрос

Когда 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<...> или 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:

Is можно кэшировать значение, вычисленное в лямбда-выражении?

Важно отметить, что лямбда-выражения лениво вычисляются в C #.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top