繁体   English   中英

LINQ与Method表达式的差异

[英]Differences in LINQ vs Method expression

为什么Linq表达式IL会导致省略Select投影,而相应的方法表达式会保留Select投影?

我想这两段代码也是一样的。

 var a = from c in companies
                where c.Length >10
                select c;

//

var b = companies.Where(c => c.Length > 10).Select(c => c);

//IL - LINQ

IEnumerable<string> a = this.companies.
Where<string>(CS$<>9__CachedAnonymousMethodDelegate1);

//IL

   IEnumerable<string> b = this.companies.Where<string>
   (CS$<>9__CachedAnonymousMethodDelegate4).Select<string, string>
   (CS$<>9__CachedAnonymousMethodDelegate5);

那为什么IL的区别呢?

编辑 :那么为什么

  var a = from c in companies
           select c;

即使在IL内部也会导致SELECT投影。 它也可以省略吗?

C#编译器很聪明,可以从Linq中删除无用的语句。 选择c没用,所以编译器将其删除。 当你编写Select(c => c)时,编译器不能说该指令是无用的,因为它是一个函数调用,所以它不会删除它。 如果你删除它自己IL变得相同。

编辑:Linq是一种“描述性”语言:你说出你想要的东西,编译器就可以很好地转换它。 您对该转换没有任何控制权。 编译器尝试优化函数调用而不使用Select因为你没有做投影所以它没用。 当你编写Select(c => c)时,你会明确地调用一个函数,所以编译器不会删除它。

var a = from c in companies select c;
var a = c.Select(elt=>elt);

在此示例中,Select非常有用。 如果你删除它有一个类型的c; 否则a是IEnumerable

@mexianto当然是正确的,这是一个编译器优化。

请注意,这在“退化查询表达式”下的语言规范中明确指出。 还要注意编译器足够聪明, 执行优化,这样做会返回原始源对象(用户可能希望使用简并查询使客户端难以改变源对象,假设它是可变的)。

7.16.2.3简并查询表达式

表单的查询表达式

from x in e select x

被翻译成

( e ) . Select ( x => x ) 

[...]简并查询表达式是一个简单地选择源元素的表达式。 翻译的后期阶段通过用其源替换它们来移除由其他翻译步骤引入的退化查询。 但是,确保查询表达式的结果永远不是源对象本身是很重要的,因为这会向查询客户端显示源的类型和标识。 因此,此步骤通过在源上显式调用Select来保护直接在源代码中编写的退化查询。 然后由Select和其他查询运算符的实现者来确保这些方法永远不会返回源对象本身。

在第二个示例中,对Select的调用不是多余的。 如果省略Select调用,查询将只返回原始集合,而Select返回IEnumerable。

在您的第一个示例中,Where已经返回IEnumerable并且select子句没有做任何工作,因此省略它。

因为在查询版本中没有实际选择将'c'投射到其他内容中,它只是按原样传递'c'。 这导致只调用'Where'。

在第二个变体中,您明确地调用“选择”,从而进行投影。 是的,您只返回相同的对象,但编译器不会看到这个。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM