是否有些函数无法转换为等效表达式
本文关键字:表达式 转换 函数 是否 | 更新日期: 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风格的可变方法调用
- 可选参数和命名参数调用
- 方法组(当然,在调用中除外)
这不是一个详尽的清单;还有其他一些奇怪的角落案例。但这应该涵盖他们中的大多数人。