c# - 从 TDelegate 到 Expression<TDelegate> 的隐式转换在哪里声明?

标签 c# .net linq lambda linq-expressions

其实有四个相关的问题:

1) 为什么可以这样做?

Expression<Func<int, int>> incrementorExpression = (i => i + 1);

但是无法做到这一点?

LambdaExpression decrementorExpression = (i => i - 1);

在第二种情况下,编译器报告如下:“无法将 lambda 表达式转换为类型‘System.Linq.Expressions.LambdaExpression’,因为它不是委托(delegate)类型”

2) TDelegate 之间的转换在哪里和 Expression<TDelegate>宣布?我想我记得以前见过它,但现在似乎找不到了。但我不能确定我是否看到了它。

3) 当我这样做时:

Expression<Func<int, int>> incrementExpression = (i => ++i);

编译器说,“表达式树不能包含赋值运算符。”为什么会这样?

4) 如果我能做到:

Expression<Func<int, int>> incrementorExpression = (i => i + 1);

那我为什么不能做this

public Expression<Func<T>> ToExpression<T>(Func<T> func)
{
  return func;
}

最佳答案

您几乎已经找到答案了。

i => i + 1不是 Func<int, int> .它是一个 lambda 表达式。 Lambda 表达式可以转换为匹配的委托(delegate)类型或匹配的表达式树类型。

如果将 lambda 表达式转换为委托(delegate)类型,编译器会将其编译为具有指定效果的 IL 代码。

如果将 lambda 表达式转换为表达式树类型,编译器会将其编译到 IL 中,IL 生成一个表达式树来表示您在 lambda 表达式中编写的内容。表达式树旨在供库稍后解析,因此表达式树与您编写的代码紧密匹配非常重要。

Func<int, int> f = i => i + 1; // okay, creates delegate.
Expression<Func<int, int>> e = i => i + 1; // okay, creates expression tree.

无法从 f 检索到任何信息关于它执行的操作。从其委托(delegate)类型可知,它需要一个 int。并返回 int ,但除此之外,它是一个黑盒子。您输入一个数字,然后输出一个数字,但您不再知道如何操作。

e ,另一方面,存储 1 的事实添加到名为 i 的参数中,甚至那个 1出现在 + 的 RHS 上.

存储在 e 中的额外信息对于那些解释表达式树的库来说通常是必不可少的,因此来自 Func<int, int> 的隐式转换至 Expression<Func<int, int>>只是行不通:不再提供所需的信息。

至于LambdaExpression decrementorExpression = (i => i - 1); ,这是无效的,因为编译器无法确定您是否需要 Expression<Func<int, int>>。 , 一个 Expression<Func<int, object>> ,或 Expression<MyFunc>其中 MyFunc是您创建的自定义委托(delegate)类型。

最后是“表达式树不能包含赋值运算符”,这主要是因为对于表达式树的预期用例,表达式包含赋值通常没有意义。不过,考虑到 .NET 表达式树能够表示赋值操作,这是一个有点武断的限制。

关于c# - 从 TDelegate 到 Expression<TDelegate> 的隐式转换在哪里声明?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27738944/

相关文章:

javascript - ASP.NET Core API 中的模型绑定(bind)始终为 null

c# - 在不同的CPU内核上执行上下文切换和线程

.net - 如何在 .NET 中编辑 EXIF 数据

c# - 是否可以使用源代码生成器来处理异常?

mysql - Devart LinqConnect for mysql 字段初始值设定项无法引用非静态字段、方法或属性

c# - HTMLagilitypack 没有删除所有 html 标签 我怎样才能有效地解决这个问题?

c# - 如果键子串存在则返回字典值

C# 异步串行端口读取

c# - 如何编写 linq 语句来获取一组记录中的最后一条记录

c# - 比较同一列表中的多个项目