在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);
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top