简体   繁体   English

Linq投影如何在扩展方法和查询表达式之间工作

[英]How does Linq projection work between Extention Method and query expression

Fiddling around with Linq, and to my surprise I meet the following: 摆弄Linq,令我惊讶的是我遇到了以下情况:

var words = new List<string>() {"seven", "ten", "one" ,"five"};

var test1 = words.OrderBy(w => w.Length);
var test2 = words.OrderBy(w => w.Lenght).Select(w => w);
var test3 = from w in words
            orderby w.Length
            select w;

And VS debug tells me VS调试告诉我

test1: System.Linq.IOrderedEnumerable<string>
test2: System.Collections.Generic.IEnumerable<string>
test3: System.Linq.IOrderedEnumerable<string>

I was expecting same type for test2 and test3 , and oh boy!, the compiler, or whatever it is, thinks otherwise. 我期待test2test3相同类型,哦男孩!,编译器,或者其他什么,不这么认为。

  1. Anyone to shed the light? 有人放光吗?
  2. Also, is there any case I'll prefer test2 instead of test1 as long as I'm projecting to the same type? 另外,有什么情况我会更喜欢test2而不是test1 ,只要我投射到同一类型? ie Select(w => w) Select(w => w)

The compiler omits the call to Select when there is no real transformation in the select clause of the query expression. 当查询表达式的select子句中没有实际转换时,编译器会忽略对Select的调用。 That's why the queries in test1 and test3 are equivalent. 这就是为什么test1test3中的查询是等价的。

My answer is based on this post from Jon Skeet's blog (read the Query expressions paragraph): LINQ to Objects 我的回答是基于Jon Skeet博客的这篇文章(阅读查询表达式段落): LINQ to Objects

var result = from x in source
                 where x < 4
                 select x; 

(...) we're not actually performing a real transformation. (...)我们实际上并没有进行真正的转型。 In that case – and so long as there's something else in the query, in this case our "where" clause – the compiler effectively omits the "select" clause (...) 在那种情况下 - 只要查询中还有其他内容,在本例中我们的“where”子句 - 编译器有效地省略了“select”子句(...)

Regarding the second part of your question, when you invoke Select at the end, you'll get an IEnumerable<T> , because that's what Select returns. 关于你问题的第二部分,当你在最后调用Select时,你会得到一个IEnumerable<T> ,因为那就是Select返回的。 IOrderedEnumerable<T> extends IEnumerable<T> , so by making a projection at the end you lose the ability to use members of the IOrderedEnumerable<T> interface. IOrderedEnumerable<T>扩展IEnumerable<T> ,因此通过在末尾进行投影,您将失去使用IOrderedEnumerable<T>接口成员的能力。

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

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