[英]How does Linq use IEnumerable methods after an IOrderedEnumerable method?
In Linq, extension methods like Where
return an IEnumerable
collection, but sorting methods like OrderBy
return an IOrderedEnumerable
collection. 在Linq中,扩展方法如
Where
返回IEnumerable
集合,但排序方法如OrderBy
返回IOrderedEnumerable
集合。
So, if you have a query that ends with OrderBy
(ie returns an IOrderedEnumerable
), you can't later append a Where
method - the compiler complains about the type being passed into Where
. 所以,如果你有一个以
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);
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. 我查看了Reflector中的程序集,看看编译器是否正在重新排序任何操作,但它似乎没有。 How does this work?
这是如何运作的?
IOrderedEnumerable<T>
extends IEnumerable<T>
so you can still use any of the extension methods. IOrderedEnumerable<T>
扩展IEnumerable<T>
因此您仍然可以使用任何扩展方法。 The reason your first block of code didn't work is because you had effectively written: 你的第一段代码不起作用的原因是因为你有效地写了:
IOrderedEnumerable<Process> query = Process.GetProcesses()
.Where(p => p.ProcessName.Length < 10)
.OrderBy(p => p.Id);
// Fail: can't assign an IEnumerable<Process> into a variable
// of type IOrderedEnumerable<Process>
query = query.Where(p => p.ProcessName.Length < 5);
That fails because query.Where(...)
only returns an IEnumerable<Process>
, which can't be assigned to the query
variable. 这失败是因为
query.Where(...)
仅返回IEnumerable<Process>
,无法将其分配给query
变量。 It's not calling Where
that's the problem - it's assigning the result back to the original variable. 它没有调用
Where
的问题 - 它将结果分配回原始变量。 To demonstrate that, this code will work just fine: 为了证明这一点,这段代码可以正常工作:
var query = Process.GetProcesses()
.Where(p => p.ProcessName.Length < 10)
.OrderBy(p => p.Id);
// Introduce a new variable instead of trying to reuse the previous one
var query2 = query.Where(p => p.ProcessName.Length < 5);
Alternatively, you can declare query to be IEnumerable<T>
to start with: 或者,您可以将查询声明为
IEnumerable<T>
以开头:
IEnumerable<Process> query = Process.GetProcesses()
.Where(p => p.ProcessName.Length < 10)
.OrderBy(p => p.Id);
// Fine
query = query.Where(p => p.ProcessName.Length < 5);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.