如何LINQ的使用方法的IEnumerable的IOrderedEnumerable方法之后?
-
21-09-2019 - |
题
在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);
我看了在反射器的组装,看看是否编译器重新排序任何操作,但它似乎并不具备。这是如何工作的?
解决方案
IOrderedEnumerable<T>
所以仍然可以使用任何扩展方法延伸IEnumerable<T>
。你的代码第一块没有工作的原因是因为你实际上已经写的:
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);
这将失败,因为仅query.Where(...)
返回一个IEnumerable<Process>
,其不能被分配给query
变量。这不是调用Where
这就是问题所在 - 它的分配结果返回给原来的变量。为了证明,该代码会工作得很好:
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);
可替换地,可以声明查询被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);
不隶属于 StackOverflow