[C#] 반복하지 않고 IEnumerable <T>의 항목을 계산합니까?

private IEnumerable<string> Tables
{
    get
    {
        yield return "Foo";
        yield return "Bar";
    }
}

그것들을 반복하고 # n의 # n 처리와 같은 것을 작성한다고 가정 해 봅시다.

주요 반복 전에 반복하지 않고 m의 값을 찾을 수있는 방법이 있습니까?

나는 나 자신을 명확하게했다.



답변

IEnumerable이것을 지원하지 않습니다. 이것은 의도적으로 설계된 동작입니다. IEnumerable지연 평가를 사용하여 요청하기 전에 필요한 요소를 가져옵니다.

당신은 당신이 사용할 수있는 그들을 반복하지 않고 항목의 수를 알고 싶은 경우에 ICollection<T>, 그것은이 Count속성을.


답변

System.Linq.Enumerable.Count확장 방법에 대한 IEnumerable<T>다음과 같은 구현이 :

ICollection<T> c = source as ICollection<TSource>;
if (c != null)
    return c.Count;

int result = 0;
using (IEnumerator<T> enumerator = source.GetEnumerator())
{
    while (enumerator.MoveNext())
        result++;
}
return result;

따라서 속성 ICollection<T>이있는 로 캐스팅하려고 시도하고 Count가능하면 사용합니다. 그렇지 않으면 반복됩니다.

따라서 최선의 방법은 객체 에서 Count()확장 방법 을 사용 IEnumerable<T>하는 것입니다.


답변

추가 정보를 추가하기 만하면됩니다.

Count()확장은 항상 반복하지 않습니다. Linq to Sql을 고려하십시오. 여기서 카운트는 데이터베이스로 이동하지만 모든 행을 다시 가져 오는 대신 Sql Count()명령을 실행하고 대신 결과를 반환합니다.

또한 컴파일러 (또는 런타임)는 객체 Count()메소드가있는 경우 객체 메소드를 호출 할 정도로 똑똑 합니다. 그래서 그건 하지 다른 조치가 완전히 무식한 항상 요소를 계산하기 위해 반복, 말하는 것처럼.

프로그래머가 확장 방법을 if( enumerable.Count != 0 )사용하여 검사 하는 경우가 많지만 Any(), if( enumerable.Any() ) linq의 지연 평가에서는 요소가 있으면 단락 될 수 있기 때문에 훨씬 효율적 이기 때문에 확장 방법을 사용하여 검사 하는 경우가 많습니다 . 더 읽기 쉽습니다


답변

내 친구에게 왜 그렇게 할 수 없는지를 보여주는 일련의 블로그 게시물이 있습니다. 그는 각 반복이 다음 소수를 리턴하는 IEnumerable을 리턴하는 함수를 작성 ulong.MaxValue하며, 다음 항목은 요청할 때까지 계산되지 않습니다. 빠르고 대중적인 질문 : 몇 개의 품목이 반환됩니까?

게시물은 다음과 같지만 길다.

  1. Beyond Loops (다른 게시물에 사용 된 초기 EnumerableUtility 클래스 제공)
  2. 반복 적용 (초기 구현)
  3. 미친 확장 방법 : ToLazyList (성능 최적화)

답변

IEnumerable은 반복없이 계산할 수 없습니다.

“정상”환경에서는 List <T>와 같이 IEnumerable 또는 IEnumerable <T>을 구현하는 클래스가 List <T> .Count 속성을 반환하여 Count 메서드를 구현할 수 있습니다. 그러나 Count 메서드는 실제로 IEnumerable <T> 또는 IEnumerable 인터페이스에 정의 된 메서드가 아닙니다. (실제로 유일한 것은 GetEnumerator입니다.) 이는 클래스 별 구현을 제공 할 수 없음을 의미합니다.

오히려 Count 메서드는 정적 클래스 Enumerable에 정의 된 확장 메서드입니다. 이는 해당 클래스의 구현에 관계없이 IEnumerable <T> 파생 클래스의 모든 인스턴스에서 호출 될 수 있음을 의미합니다. 그러나 이는 해당 클래스 외부의 단일 위치에서 구현됨을 의미합니다. 물론이 클래스의 내부와 완전히 독립적 인 방식으로 구현되어야 함을 의미합니다. 계산하는 유일한 방법은 반복을 통한 것입니다.


답변

또는 다음을 수행 할 수 있습니다.

Tables.ToList<string>().Count;


답변

아니요, 일반적으로 아닙니다. 열거 형을 사용할 때 한 가지 요점은 열거의 실제 개체 집합을 알 수 없다는 것입니다 (사전 또는 전혀 아님).