2016-11-28 7 views
3

간단한 팁으로 IEnumerable.Any()를 사용하는 경우가 많습니다. 그 이유는 전체 열거 형을 반드시 통과시켜야하기 때문입니다.컴파일러는 IEnumerable <T> .Count()에 대한 비교를 최적화합니까?

방금 ​​Enumerable에 단일 항목 또는 다중 항목이 있는지 확인하려고하는 코드 세그먼트를 작성했습니다. 내가 궁금해 만든

if (reportInfo.OrebodyAndPits.SelectMany(ob => ob.Pits).Count() > 1) 
{ 
    ws.Cells[row, col++].Value = "Pits"; 
} 
else 
{ 
    ws.Cells[row, col++].Value = "Pit"; 
} 

는 비교가 첫 번째 항목을지나 열거 즉시 false를 돌려 똑똑 형태로 컴파일 할 것인가?

그렇지 않다면, 할 수있는 linq 확장 메소드를 작성하는 방법이 있습니까?

(나는이 코드 조각의 성능에 미치는 영향에 정말 관심 없어, 유의하시기 바랍니다. 나는 주로 궁금 하군요.)

+2

아니요, .Count()는 항목 수를 반환합니다. '123456789' 그리고 단지'> 1' 조건을 확인하십시오. 똑똑한 행동을 위해'Skip (1) .Any()'를 넣으십시오. 어떤 경우에는 (* 하나 제외 된) * .Net은'IEnumerable '이 실제로 배열 *'T []'또는 * list *'List '이라는 것을보고 트래킹 대신에'Length' 또는'Count'를 호출합니다 그러나 우리가 기대할 수있는 것은 이것입니다. –

답변

4

아니,하지 않습니다. 귀하의 코드는 순서의 모든 항목을 계산합니다. 이것은 LINQ 문이 컴파일러에 의해 최적화되지 않았기 때문에 작성한 내용이 사용자가 얻는 것입니다.

equivelent는 순서가 1 개 이상의 항목이 포함되어 있는지 여부를 확인하는보다 효율적인 방법입니다 : 모든 항목이 남아 있는지 여부를

reportInfo.OrebodyAndPits.SelectMany(ob => ob.Pits).Skip(1).Any(); 

이는 첫 번째 항목을 건너 뛰는 후, 확인합니다.

3

무언가가 작동하는 이유를 알고 싶다면 왜 소스 코드를 보지 않으시겠습니까? 당신이 설명하는 것처럼 컴파일러가 최적화를 할 수 없습니다 https://github.com/dotnet/corefx/blob/master/src/System.Linq/src/System/Linq/Count.cs#L12

: https://github.com/dotnet/corefx/blob/master/src/System.Linq/src/System/Linq/AnyAll.cs#L20 여기

Count() 방법 :

다음은 Any() 방법입니다. 그것은 카운트를 요구하고 숫자를 얻은 다음 조건문에있는 숫자와 그 숫자를 비교합니다.

하지만 최적화를 시도합니다. Count() 메서드에서 볼 수 있듯이 IEnumerable이 이미 Count 속성을 지원하는지 확인하고 모든 요소를 ​​다시 계산하는 것보다 빠르기 때문에이를 사용합니다. 사용할 수없는 경우 전체 내용을 이동해야하며 개별적으로 계산해야합니다.

IEnumerable에 적어도 두 개가 있는지를 결정하는 LINQ 메서드 (확장 메서드 인 IEnumerable<T>)를 작성하려면 충분히 쉽게 작성해야합니다. 다음과 같이 입력합니다.

예 :

public static bool AtLeastTwo<TSource>(this IEnumerable<TSource> source) 
    { 
     if (source == null) 
     { 
      throw Error.ArgumentNull(nameof(source)); 
     } 

     using (IEnumerator<TSource> e = source.GetEnumerator()) 
     { 
      e.MoveNext(); // Move past the first one 
      return e.MoveNext(); // true if there is at least a second element. 
     } 
    } 
+0

Skip + Any는 더 쉽고 확장 메서드가 필요하지 않습니다. – Wazner

+0

하지만 그건 물어 보지 않았습니다 : "그렇지 않다면, linq 확장 메소드를 작성하는 방법이 있습니까?" –