Linq 如何在 IOrderedEnumerable 方法之后使用 IEnumerable 方法?
在 Linq 中,Where
等扩展方法返回 IEnumerable
集合,但 OrderBy
等排序方法返回 IOrderedEnumerable
集合。
因此,如果您有一个以 OrderBy
结尾的查询(即返回 IOrderedEnumerable
),则以后无法附加 Where
方法 -编译器抱怨类型被传递到 Where
。
var query = Process.GetProcesses()
.Where(p => p.ProcessName.Length < 10)
.OrderBy(p => p.Id);
query = query.Where(p => p.ProcessName.Length < 5);
但是,如果您在一个查询中完成所有操作,那就没问题了!
var query = Process.GetProcesses()
.Where(p => p.ProcessName.Length < 10)
.OrderBy(p => p.Id)
.Where(p => p.ProcessName.Length < 5);
我查看了 Reflector 中的程序集,看看编译器是否对任何操作进行了重新排序,但似乎没有。这是如何运作的?
In Linq, extension methods like Where
return an IEnumerable
collection, but sorting methods like OrderBy
return an IOrderedEnumerable
collection.
So, if you have a query that ends with OrderBy
(i.e. returns an IOrderedEnumerable
), you can't later append a Where
method - the compiler complains about the type being passed into Where
.
var query = Process.GetProcesses()
.Where(p => p.ProcessName.Length < 10)
.OrderBy(p => p.Id);
query = query.Where(p => p.ProcessName.Length < 5);
However, if you do it all in one query, it's fine!
var query = Process.GetProcesses()
.Where(p => p.ProcessName.Length < 10)
.OrderBy(p => p.Id)
.Where(p => p.ProcessName.Length < 5);
I've looked at the assembly in Reflector to see if the compiler was re-ordering any of the operations, but it doesn't seem to have. How does this work?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
IOrderedEnumerable
扩展了IEnumerable
,因此您仍然可以使用任何扩展方法。您的第一个代码块不起作用的原因是您有效地编写了:失败是因为
query.Where(...)
仅返回IEnumerable
,不能分配给query
变量。问题不在于调用Where
- 而是将结果分配回原始变量。为了证明这一点,此代码可以正常工作:或者,您可以将查询声明为
IEnumerable
来开始:IOrderedEnumerable<T>
extendsIEnumerable<T>
so you can still use any of the extension methods. The reason your first block of code didn't work is because you had effectively written:That fails because
query.Where(...)
only returns anIEnumerable<Process>
, which can't be assigned to thequery
variable. It's not callingWhere
that's the problem - it's assigning the result back to the original variable. To demonstrate that, this code will work just fine:Alternatively, you can declare query to be
IEnumerable<T>
to start with: