3

在 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 中的程序集,看看编译器是否重新排序了任何操作,但似乎没有。这是如何运作的?

4

1 回答 1

9

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);
于 2009-10-13T09:32:07.900 回答