λ是否->;表达式树转换过程在任意位置指定
本文关键字:过程 任意 位置 转换 是否 gt 表达式 | 更新日期: 2023-09-27 18:29:05
在C#中编译LINQ查询有两个重要步骤。第一个是将LINQ查询语法转换为方法调用链,如C#语言规范的7.16节所述。此转换过程的指定非常详细,语言开发人员可以使用它在新的CLR语言上实现类似的查询语法。
第二步是将lambda表达式转换为表达式树,这发生在调用返回IQueryable
的查询方法时,而不是在调用返回IEnumerable
的方法时。是否指定了这种转换是如何发生的,与查询语法转换过程的解释类似?
表达式树的构造实际上是显式而不是定义的。编译器开发人员可以自由使用他们想要的任何方法,当然前提是执行表达式会产生与调用lambda相同的结果。
这是引用C#语言规范:
6.5.2评估匿名函数转换为表达式树类型
将匿名函数转换为表达式树类型会生成表达式树(§4.6)。更准确地说,对匿名函数转换的评估会导致构建一个表示匿名函数本身结构的对象结构表达式树的精确结构以及创建它的确切过程都是由实现定义的
我在末尾加了黑体字。
我怀疑这是故意不指定的,目的是让编译器开发人员可以自由地实现他们认为有用的任何优化。表达式树的严格规范将阻止这种情况的发生。
有没有具体说明这种转变是如何发生的,可以比较对查询语法转换过程的解释?
正如NSFW所说,没有
在实践中,这些表达式树可以在不同的框架之间变化。现实生活中的一个例子是:
我们使用expression lambdas
通过表达式树来获取属性信息。
如void DoSomething<P, K>(P model, Expression<Func<P, K> propertySelector)
和使用DoSomething(model, m => m.Property)
实际财产询问是在DoSomething
内部通过反射进行的。这是非常经典的,并且这种代码的变体存在于inteet中。
现在,这很酷,它在.NET 4.0中运行得很好。然而,我一尝试4.5,它就彻底崩溃了,因为底层的表达式树已经改变了。
可以肯定的是,Roslyn会引入很多新的"bug",因为一些客户端代码依赖于Lambda如何转换为表达式树的表示(如果你真的坚持这样做,那么使用Visitor
类可以最大限度地减少破坏的机会)。
确保表达式树保持不变将是一项主要任务,同时也会限制(例如速度)