2009-10-13 3 views
2

Linq에서 Where과 같은 확장 방법은 IEnumerable 컬렉션을 반환하지만 OrderBy과 같은 정렬 방법은 IOrderedEnumerable 컬렉션을 반환합니다. 당신이 (즉,이 IOrderedEnumerable를 반환) OrderBy로 끝나는 질의가있는 경우Linq는 IOrderedEnumerable 메서드 다음에 IEnumerable 메서드를 어떻게 사용합니까?

그래서, 당신은 나중에 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>이므로 확장 방법을 계속 사용할 수 있습니다. 코드의 첫 번째 블록이 작동하지 않은 이유는 효과적으로 작성했기 때문이다

query.Where(...)query 변수에 할당 할 수없는 IEnumerable<Process>를 반환하기 때문에 실패
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); 

. Where이 문제가 아니며 결과를 원래 변수에 다시 지정합니다. 그것을 설명하기 위해,이 코드는 잘 작동합니다

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

네,하지만 두 예제의 차이점은 무엇입니까 :

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>를로 선언 할 수 있습니다? 왜 두 번째 작품은 효과가 있지만 첫 번째 작품은 그렇지 않습니까? –

+5

두 번째 것은'IOrderedEnumerable '유형의 변수에'IEnumerable '표현식을 할당하려고 시도하지 않습니다. –