2010-01-02 2 views

답변

17

"이것이 사실인지 상상해보십시오."

모든 열거 메서드가 단일 인터페이스에있는 경우 두 호출자가 같은 목록을 동시에 열거 할 수 있습니까?

하나는 "나를 열거 할 수 있습니다"라고 말했고 다른 하나는 "주어진 열거 작업을 추적하는 개체가 있습니다"라는 두 인터페이스가 있습니다.

IEnumerable 인터페이스는 원하는만큼 객체를 IEnumerator 개 생성하는 팩토리입니다. 이러한 열거 자의 사용 방법 및시기는 소비자의 몫입니다.

+1

collaped +1로한다. 이것은 왜 인터페이스가 분리되어 있고 분리되어 있는지 보여주는 좋은 예입니다. 또 다른 이유는 동일한 유형 컬렉션이 여러 가지 방법으로 열거 될 수 있다는 것입니다. 바이너리 트리를 상상해보십시오. 접두어, 중위 어, 후위 및 너비 우선 탐색을 수행 할 수 있습니다 (이름을 지정하기 만하면됩니다). 인터페이스를 분리하여 유지하면 단일 구조의 간단한 인터페이스를 통해 같은 구조에서 여러 종류의 탐색을 수행 할 수 있습니다. – LBushkin

+0

답변 해 주셔서 감사합니다. 이것은 지금 나에게 더 분명하다. –

7

IEnumerable는 객체가 수집 또는 선형 방식으로 반복 처리 할 수있는 데이터의 출처는 것을 의미한다. IEnumerator은 반복을 수행하는 실제 구현을위한 인터페이스입니다.

4

"IEnumerable"은 "와서 나를 열거하십시오"라고 말하고 (그렇다면 열거자를 어떻게 말합니까?) "IEnumerator"는 "나는 당신의 컬렉션을 열거 할 수 있습니다!"라고 말합니다. 그리고 이미 가지고 있다면, 더 이상 얻을 필요가 없습니다.

0

종종 열거하는 것은 열거 된 것과 관련하여 접선 방향으로 만 접하게됩니다. IEnumerable과 IEnumerator가 동일한 인터페이스 인 경우 공유 할 수 없거나 열거 할 개체를 전달할 수 있도록 GetEnumerator에 형식화되지 않은 인수가 있어야합니다. 이들을 분할하면 열거 인프라가 잠재적으로 여러 유형에서 공유 될 수 있습니다.

2

여기에 아주 좋은 답변이 있습니다. 단지 몇 가지 강조. 열거자는 상태를 유지하고 열거 된 컬렉션의 현재 개체를 추적합니다. IEnumerator.Current를 통해 사용할 수 있습니다. 그리고 IEnumerator.MoveNext()를 변경하는 방법을 알고 있습니다. 상태를 유지하려면 상태를 저장하는 별도의 객체가 필요합니다. 하나의 컬렉션 객체 만 있기 때문에 그 상태를 컬렉션 객체 안에 쉽게 저장할 수는 없지만 하나 이상의 열거자를 가질 수 있습니다.

"쉽게"라는 표현을 사용했는데 실제로 컬렉션이 열거자를 추적 할 수 있기 때문입니다. 결국 그것은 반복자를 반환 한 컬렉션 클래스의 GetEnumerator() 메서드에 대한 호출이었습니다. .NET Framework에는 Microsoft.VisualBasic.Collection이라는 하나의 컬렉션 클래스가 있습니다. Collection 클래스에 대해 VB6 계약을 구현해야하며이 계약은 컬렉션이 열거되는 동안 컬렉션을 변경하는 것이 합법적이라고 명시합니다. 즉, Collection이 수정되면 생성 된 모든 반복자 객체에 대해 합리적이어야합니다.

그들은 훌륭한 트릭을 만들었습니다. WeakReference가이 점에 영감을 받았을 수도 있습니다. 반사경에 표시된 코드를 확인하십시오. 영감을주는 물건. 좀 더 파고 컬렉션 클래스에서 "버전"을 찾으십시오. 대단한 트릭.

+0

나는 왜 그걸 할 수있는 클리너 컬렉션을 사용할 수 없었는지 궁금하다. 컬렉션을 통해 열거하고 선택적으로 요소를 삭제하면 일반적인 작업처럼 보일 것입니다. – supercat

+0

@ 수퍼 : 근본적으로 부서지기 때문입니다. 컬렉션의 단일 변형에 대한 반복자를 보완 할 수 있습니다. 그러나 요소를 제거하고 다른 위치에 다시 삽입하는 것과 같은 것은 무언가를 깨뜨릴 것입니다. 반복자는 요소를 두 번 표시하거나 전혀 표시하지 않습니다. 그 외에도 반복자의 모든 실제 인스턴스를 추적하는 것은 비용이 많이 듭니다. –

+0

'정상적인'컬렉션은 그러한 기능을 지원하지 않지만 Collection은 유용한 의미를 갖도록 관리합니다. 유용하게 쓰일 수있는 의미를 지니고 있습니다. 하나는 그러한 의미를 모든 곳에서 원하지 않지만 때로는 멋지다. 사실, 나는 더 많은 iEnumerator의 맛을 보았을 것이다. 응용 프로그램은 필요한 의미 체계에 따라 하나를 선택할 수 있습니다 (일부는 메소드를 추가하고 다른 메소드는 보증을 추가합니다). 유용한 것은 iPurgeEnumerator입니다 : 각 항목과 함께 술어를 호출하고 참이면 삭제하십시오. – supercat

0

minlinq에 Bart De Smet의 게시물을 읽은 후 더 이상 두 인터페이스를 분할하는 것이 엄격히 요구된다고는 생각하지 않습니다.예컨대

은 - 상기 링크에서,는 IEnumerable/IEnumerator를 단일 메소드 인터페이스

Func<Func<Option<T>>> 

및 기본적인 구현

public static class FEnumerable 
{ 
    public static Func<Func<Option<T>>> Empty<T>() 
    { 
     return() =>() => new Option<T>.None(); 
    } 

    public static Func<Func<Option<T>>> Return<T>(T value) 
    { 
     return() => 
     { 
      int i = 0; 
      return() => 
       i++ == 0 
       ? (Option<T>)new Option<T>.Some(value) 
       : (Option<T>)new Option<T>.None(); 
     }; 
    } 

    ... 

} 

public static Func<Func<Option<T>>> Where<T>(this Func<Func<Option<T>>> source, Func<T, bool> filter) 
{ 
    return source.Bind(t => filter(t) ? FEnumerable.Return(t) : FEnumerable.Empty<T>()); 
} 
관련 문제