是否有些函数无法转换为等效表达式

本文关键字:表达式 转换 函数 是否 | 更新日期: 2023-09-27 18:19:31

这是我之前问过的一个问题的后续内容,在这里可以看到:

对传递Expression与Func参数感到困惑

接受的答案建议将引用本地对象的表达式重构为Linq to Entities可以在后台存储(在我的例子中是SQL Server)上实际执行的东西

我花了很长时间试图想出一些对我正在做的事情有效的东西。我的原始

Func<Thing, bool> whereClause

正在引用本地Dictionary对象,而Linq to Entities或SQL在运行时无法理解该对象。我试着重构成多个列表,这些列表伪造了一个字典,然后是数组。每次,我都会遇到运行时错误,抱怨上下文无法识别List上的方法或数组索引器之类的东西。

最终,我放弃了,只提供了一个额外的方法,当我无法找到正确的表达式时,它会使用Func参数。

我并没有试图找到解决我特定问题的方法,我只是想知道一般情况下是否总是可以转换,比如

Func<Thing, bool>

等效

Expression<Func<Thing, bool>>

其可以针对Linq to Entities运行。或者,如果有许多查询示例,您只需就必须先将数据拉入内存。

是否有些函数无法转换为等效表达式

您不会将Func转换为表达式树-编译器会将lambda表达式转换为表达式树形。。。不,这并不总是可能的。例如,不能将语句lambda转换为表达式树:

Expression<Func<string, int>> valid = text => text.Length;
Expression<Func<string, int>> invalid = text => { return text.Length; };

还有其他各种限制。

即使可以创建表达式树(如果手动创建,则可以构建C#编译器不会创建的表达式树,尤其是在.NET4中),这与表示LINQ to SQL(等)可以适当翻译的内容的表达式树也不一样。

Jon当然是正确的;您可以将lambda转换为表达式树。

为了扩展一下他的"各种其他限制"手工:转换为表达式树的lambda可能不包含:

  • 语句
  • 主要用于状态突变的表达式:赋值、复合赋值、递增和递减运算符
  • 任何类型的动态操作
  • 多维数组初始值设定项
  • 删除的分部方法
  • 基本访问
  • 任何类型的指针操作
  • sizeof(T),除了其中T是内置类型
  • COM样式索引的属性调用
  • COM风格的"可选ref"调用
  • C风格的可变方法调用
  • 可选参数和命名参数调用
  • 方法组(当然,在调用中除外)

这不是一个详尽的清单;还有其他一些奇怪的角落案例。但这应该涵盖他们中的大多数人。