表达式 < Func < > 与 Func < > 的差异

例如,为什么大多数 LINQ 运算符接受 Expression<Func<TSource>>和它的等效 Func<TSource>

使用通用 Expression类而不是直接使用 lambda 语法的好处/原因是什么?

21725 次浏览

使用 Expression<T>显式地创建一个 表达式树-这意味着你可以像处理数据一样处理组成查询的代码。

原因是 LINQ 提供程序(例如 LINQ to SQL)检查查询本身,以确定将 C # 表达式转换为 T-SQL 查询的最佳方法。由于表达式树允许您将代码视为数据,因此提供程序可以这样做。

Func<T>创建一个可执行函数。

Expression<Func<T>>创建一个表达式树,允许您将函数中的代码作为数据处理。

表达式树允许您执行 LINQtoSQL 和 LINQtoXML 之类的操作,方法是从。NET 代码。

Expression<Func<>>是尚未转换为代码的函数的表示形式。Func<>是一个实际的可执行函数。使用前者允许您在调用表达式时将其转换为适当的函数。例如,对于 LINQtoSQL,这将把它转换成等效的代码来执行 SQL 语句并返回指定的内容。使用 LINQ to 对象,它将使用 CLR 在客户机上执行代码。Func<>总是在 CLR 中执行——它是可执行代码。

总之,两者之间的主要区别如下:

  • Expression<Func<...>> 是表示原始源代码的 表达式树(它存储在与原始 C # 代码非常接近的树状数据结构中)。在这种形式下,你可以分析源代码,像 LINQ to SQL 这样的工具可以将表达式树(源代码)翻译成其他语言(例如,LINQ to SQL 的情况下是 SQL,但是你也可以将目标定位为 JavaScript)。

  • Func<...> 是您可以执行的普通委托。在这种情况下,编译器将函数体编译为中间语言(IL) ,就像编译标准方法一样。

值得一提的是,Expression<..>有一个 Compile方法,该方法在运行时编译表达式并生成 Func<...>,因此需要从第一个方法转换到第二个方法(带有一些性能开销)。但是,没有从第二个到第一个的转换,因为一旦获得 IL,就很难(不可能)重建原始源代码。