表达式树如何提供对局部变量的访问? [英] How do Expression Trees provide access to local variables?

查看:84
本文介绍了表达式树如何提供对局部变量的访问?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个问题与闭包的工作方式无关.这个问题与LINQ如何决定在运行时可分析表达式中引用什么以及对表达式进行评估和放入什么内容有关.

This question is not related to how closures work. This question is about how LINQ decides what to quote into a runtime parsable expression, and what to evaluate and put into that expression.

这个问题试图理解LINQ的工作原理,以另一种语言实现类似的东西.

This question is trying to understand how LINQ works, to implement something similar in another language.

请考虑以下LINQ查询,以将其转换为表达式树:

Consider the following LINQ query, to be converted into an expression tree:

var my_variable = "abc";
var qry = from x in source.Foo
          where x.SomeProp == my_variable
          select x.Bar;

由编译器映射为代码:

var qry = source.Foo
           .Where(x => x.SomeProp == my_variable)
           .Select(x => x.Bar);

当将其转换为表达式树时,LINQ如何知道要在表达式中引用哪些内容,以及要对哪些进行评估并将结果放入表达式中?

When this is converted to an expression tree, how does LINQ know which to quote into expressions, and which to evaluate and put results into the expressions?

例如,如何知道评估my_variable并将结果放入expressino,但是将x.SomeProp==转换为LINQ表达式树的一部分?

For example, how does it know to evaluate my_variable and put the result into the expressino, but convert x.SomeProp and == into parts of the LINQ Expression Tree?

C#编译器是否对LINQ引用了哪些表达式进行了硬编码的特殊列表? (即可以转换为SQL的最外面的操作,包括:==,!=,&&,||,<,>,< =,> =,子字符串等)

Does the C# compiler have a hard-coded special list of which expressions are quoted for LINQ? (i.e. the outer-most operations which can be translated into SQL, including: ==, !=, &&, ||, <, >, <=, >=, substring, etc)

推荐答案

只需检查一下它是否清楚.SomeProp依赖于x,并且x在表达式树解析时就不确定,因为它是先前函数的输出(其中).

Just by examination its clear that .SomeProp is dependent on x and x is not deterministic at expression tree parsing time, because its an output of a prior function (where).

my_variable不是表达式树中任何表达式的输出,因此它的值可能在表达式树解析时就知道了,但是即使知道它的值也很可能不会被烘焙",因为那样会阻止编译后的表达式树被重用,因此它将被视为表达式树评估中的输入值.

my_variable is not an output of any expression in the expression tree so its value might be known at expression tree parsing time, but its quite likely not to be 'baked in' even if it is known because that would prevent the compiled expression tree from being reused, so it will just be treated as an input value into the expression tree evaluation.

我还没有反编译linq,但是您可以考虑以下表达式树;

I haven't decompiled linq, but you could consider the following expression tree;

ExpressionTree myEx = new ExpressionTree(
   new MultiplicationExpression(
      new InputVariableExpression("@MyInputVar"),
      new ConstantExpression(22)
   )
);

要评估,您可以致电

Dictionary<string, object> inputVars = new Dictionary<string, object>();
inputVars.Add("@MyInputVar",16);
int result = myEx.Evaluate(inputVars);

解析器可能选择烘焙常量表达式,因为它知道"它不能改变,但是请考虑以下内容;

The parser might choose to bake in the constant expression, because it 'knows' it cannot change, but consider the following;

ExpressionTree anotherEx = new ExpressionTree(
   new AdditionExpression(
      myEx,
      new InputVariableExpression("@MyNextInputVar")
   )
);

这在概念上类似于在Linq x =>中使用替换变量,其中myEx是存储的表达式树,但实际上不是表达式的结果.表达式解析器在执行之前无法独立知道myEx的值.

This is similar in concept to using a replacement variable in Linq x => where myEx is a stored expression tree, but not actually the result of the expression. The expression parser cannot independently know what the value of myEx is until execution time.

Dictionary<string, object> inputVars = new Dictionary<string, object>();
inputVars.Add("@MyInputVar",16);
inputVars.Add("@MyNextInputVar",45);
int result = anotherEx.Evaluate(inputVars);

因此,此执行代码将在评估anotherEx的过程中固有地评估myEx.如果myEx中仅包含ConstantExpression元素,则可能仅对其进行一次评估并缓存了结果,但由于它包含范围外的InputVariableExpression,因此很明显,无法评估一次评估的结果,无法以后使用

So this execution code will inherently evaluate myEx during the evaluation of anotherEx. If myEx had only ConstantExpression element in it, it might be evaluated only once and the result cached, but because it contains an out-of-scope InputVariableExpression its clear the result of one evaluation cannot be cached for subsequent use.

这篇关于表达式树如何提供对局部变量的访问?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆