代码之家  ›  专栏  ›  技术社区  ›  Damian Powell

编译表达式时,它是否隐式缓存?

  •  16
  • Damian Powell  · 技术社区  · 16 年前

    当一个 Expression<T> 编译后,结果代码是否被框架隐式缓存?我在沿着静电线思考 Regex 方法,其中框架隐式编译并缓存最后几个正则表达式。

    如果编译 表达式<t> 对象是 缓存,您能推荐一些最佳实践来保持编译时间的缩短,或者如果我手动缓存一个表达式,任何可能导致问题的gotchas吗?

    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 就像编译表达式时一样,而不是从堆栈中的适当位置检索这些值(即,而不是获取当前值)。

    2 回复  |  直到 15 年前
        1
  •  10
  •   Marc Gravell    16 年前

    不;我不相信是这样;如果你想把它缓存起来,你必须抓住 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;
    }
    

    也就是说,将表达式的数字参数设置为 实际的 它在运行时(而不是表达式中的常量)。

        2
  •  2
  •   Community CDub    8 年前

    lambda专家不会自动缓存。为此,您需要实现自己的缓存/内存化算法。检查相关StackOverflow问题:

    Is it possible to cache a value evaluated in a lambda expression?

    重要的是要注意lambda表达式是在c_中惰性计算的。