lambda表达式树转换过程是否有规定?

8
编译C#中的LINQ查询有两个重要步骤。第一个步骤是将LINQ查询语法转换为方法调用链,具体规定在C#语言规范的第7.16节中。该转换过程已经规定得足够详细,以至于语言开发人员可以使用它来在新的CLR语言上实现类似的查询语法。 第二步是将Lambda表达式转换为表达式树,在调用返回“IQueryable”的查询方法时发生,而不是调用返回“IEnumerable”的方法时。这个转换过程是否被详细规定,与查询语法转换过程的解释相似?
2个回答

5
构建表达式树并没有明确的定义。实际上,编译器开发人员可以使用任何方法,只要执行表达式产生与调用lambda相同的结果即可。这是来自C#语言规范的一句话:将匿名函数转换为表达式树类型会产生一个表达式树(§4.6)。更准确地说,对匿名函数转换的评估导致构造表示匿名函数本身结构的对象结构。表达式树的精确结构以及创建它的确切过程是实现定义的。我在末尾添加了黑体字。我怀疑这是故意不指定的,以给编译器开发人员提供实现任何有帮助的优化的自由。如果表达式树的规范过于严格,就会阻止这种优化。

0
NSFW已经指出,没有明确说明这种转换是如何进行的,类似于查询语法转换过程的解释。 从实际角度来看,这些表达式树可能会因框架而异。一个现实的例子是这样的: 我们使用表达式树通过表达式lambda获取属性信息。 例如,void DoSomething(P model, Expression> propertySelector),以及使用DoSomething(model, m => m.Property) 实际的属性审讯是在DoSomething内部通过反射完成的。这是非常经典的,这样的代码变体在互联网上存在着。 现在,这很酷,它在.NET 4.0中运行得很好。然而,一旦我尝试4.5,它就完全崩溃了,因为底层的表达式树已经改变了。您可以确定Roslyn将引入许多新的“错误”,因为一些客户端代码依赖于lambda被转换为表达式树的表示方式(如果您真的坚持这样做——使用Visitor类可以最大程度地减少破坏的机会)。

确保表达式树保持不变将是一项重大任务,这也会限制速度(例如)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,