2010-04-14 4 views
2

MSDN의이 예의 경우 GetEnumerator 메서드에서 PeopleEnumIEnumerator을 반환합니까?GetEnumerator 메서드에서이 예제에서 (get from msdn) 이유는 새로운 PeopleEnum이 IEnumerator를 반환합니까?

public class Person 
{ 
    public Person(string fName, string lName) 
    { 
     this.firstName = fName; 
     this.lastName = lName; 
    } 

    public string firstName; 
    public string lastName; 
} 

public class People : IEnumerable 
{ 
    private Person[] _people; 
    public People(Person[] pArray) 
    { 
     _people = new Person[pArray.Length]; 

     for (int i = 0; i < pArray.Length; i++) 
     { 
      _people[i] = pArray[i]; 
     } 
    } 
    //why??? 
    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return (IEnumerator) GetEnumerator(); 
    } 

    public PeopleEnum GetEnumerator() 
    { 
     return new PeopleEnum(_people); 
    } 
} 

public class PeopleEnum : IEnumerator 
{ 
    public Person[] _people; 

// Enumerators are positioned before the first element 
// until the first MoveNext() call. 
int position = -1; 

public PeopleEnum(Person[] list) 
{ 
    _people = list; 
} 

public bool MoveNext() 
{ 
    position++; 
    return (position < _people.Length); 
} 

public void Reset() 
{ 
    position = -1; 
} 

object IEnumerator.Current 
{ 
    get 
    { 
     return Current; 
    } 
} 

public Person Current 
{ 
    get 
    { 
     try 
     { 
      return _people[position]; 
     } 
     catch (IndexOutOfRangeException) 
     { 
      throw new InvalidOperationException(); 
     } 
    } 
} 

UPDATE : 배열 데이터 타입이 ICloneable 인터페이스를 구현하는 경우 BTW, 왜 MSDN은 루프를 작성하여 _people하는 pArray 복사했다?

+1

사실, 여기 * 아무것도 * 않는 것은 놀라운 일이다 - 그것은 또한 단지 (IEnumerator''로) 수'_people.GetEnumerator() 반환;' –

+0

@Marc을 : 또는 그 문제에 관해서는 파생 수 콜렉션 :) – Josh

+0

@Josh - 1.1 예제처럼 보입니다. –

답변

3

IEnumerable 인터페이스를 올바르게 구현하려면 정확히IEnumerator을 반환해야합니다. 그것은 그래서 당신은 PeopleEnum를 참조 공공 API에,에 "명시 적 인터페이스 구현"을 사용하여이 일을하고 있지만 IEnumerable는 여전히 행복

그러나 실제로 당신은 은 매우 드물게 열거에게이 방법을 쓴다 C# 2.0 위; 반복기 블록 (yield return)을 사용하십시오. C# in Depth 6 장 (무료 장!)을 참조하십시오.

PeopleEnum이 존재하는 이유 전혀 여기은 .NET 1.1 샘플처럼 보입니다. 여기서는 입력 된 열거자를 만드는 유일한 방법입니다. .NET 2.0 이상에서는 IEnumerable<T>/IEnumerator<T>이 있는데이 유형에는 (제네릭을 통해) .Current이 입력됩니다.

.NET 2.0

/C# 2.0 (이상) 단순히 것이다 : IEnumerable을 구현

public class People : IEnumerable<Person> { 
    /* snip */ 
    public IEnumerator<Person> GetEnumerator() { 
     return ((IEnumerable<Person>)_people).GetEnumerator(); 
    } 
    IEnumerator IEnumerable.GetEnumerator() { return _people.GetEnumerator();} 
} 
+0

실제로 "결코"너무 가혹합니다. goto를 결코 사용하지 않는 것처럼 수율은 약간 느립니다. 따라서 희소 한 경계선에서는 수율을 사용하지 않는 경우가 있습니다. 하지만 다시 한 번 말하지만, 이것은 정말로 드문 일입니다. -1이 아닙니다, 단지 메모입니다. – TomTom

+0

@TomTom - 매우 드물게 개정 ;-p –

2

종류가있는 IEnumerator를 반환하는 GetEnumerator라는 방법을 필요로한다. 이 예제 (C# 2.0에서는 꽤 쓸데없는)에는 IEnumerator를 구현하는 열거 자 클래스 PeopleEnum이 있습니다. 그것은 내부적으로 C# foreach 문에 사용되는 것입니다.

최신 예제는 다음과 같이 보입니다. 이제는 C#이 반복자를 지원하므로 더 이상 PeopleEnum 클래스가 필요하지 않습니다. 효과적으로 컴파일러는 모든 어려운 작업을 처리합니다.

public class People : IEnumerable 
{ 
    private Person[] _people; 
    public People(Person[] pArray) 
    { 
     _people = new Person[pArray.Length]; 

     for (int i = 0; i < pArray.Length; i++) 
     { 
      _people[i] = pArray[i]; 
     } 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     for (int i=0; i < _people.Length; i++) { 
      yield return _people[i]; 
     } 
    } 
} 
+0

타입이없는 경우'_people.GetEnumerator()'를 반환 할 수도 있습니다 ... –

+0

그래, 개인적으로 IEnumerable을 직접 구현 한 마지막 시간을 개인적으로 기억할 수도 없습니다 . 저는 열거 자 클래스가 현재 거의 멸종되었다는 사실을 지적하고있었습니다. – Josh

+0

나는 최근에 하나를 썼지 만 C# 1.2 ;-p를 지원했다. –

관련 문제