2009-10-13 143 views
2

在Linq中,扩展方法如Where返回IEnumerable集合,但排序方法如OrderBy返回IOrderedEnumerable集合。Linq在IOrderedEnumerable方法之后如何使用IEnumerable方法?

所以,如果你有与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); 

我看着在反射大会,看是否编译器重新排序任何操作,但它似乎并不具备。这个怎么用?

回答

8

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); 
+0

是的,但正是这两个例子之间的区别?为什么第二个工作,但第一个不工作? – 2009-10-13 09:34:43

+5

第二个不试图将'IEnumerable '表达式分配到类型为'IOrderedEnumerable '的变量中。 – 2009-10-13 09:35:57