表达式<func <>&gt;之间的差异和Func&lt;&gt; </func <>

时间:2010-04-19 01:57:07

标签: c# linq

举个例子,为什么大多数LINQ运算符接受Expression<Func<TSource>>及其等价的Func<TSource>

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

4 个答案:

答案 0 :(得分:59)

使用Expression<T>明确创建expression tree - 这意味着您可以将构成查询的代码视为数据。

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

答案 1 :(得分:31)

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

  • Expression<Func<...>> 表达式树,它代表原始源代码(它存储在非常接近的树状数据结构中到原来的C#代码)。在这种形式中,您可以分析源代码和LINQ to SQL之类的工具可以将表达式树(源代码)转换为其他语言(例如,在LINQ to SQL的情况下使用SQL,但您也可以使用例如JavaScript)。

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

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

答案 2 :(得分:18)

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

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

表达式树允许您通过从.NET代码生成基础调用来执行LINQ to SQL和LINQ to XML等操作。

答案 3 :(得分:7)

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