2014-01-30 1 views
0

내부 목록을 반복자로 표시하여 호출하는 메서드가 foreach 루프로 제한되지는 않지만 IEnumerator.Current 및 IEnumerator.MoveNext()를 호출합니다.IEnumerator <string> .Current는 항상 null을 반환합니다.

public IEnumerator<string> Iterator 
{ 
    get 
    { 
     return m_list.GetEnumerator(); 
    } 
} 

public IEnumerator<string> Iterator 
{ 
    get 
    { 
     for (int i = 0; i < m_list.Count; i++) 
     { 
      yield return m_list[i]; 
     } 
     yield break; 
    } 
} 

모두는 다음 테스트에서 OutOfMemoryException을 갈 테스트 원인 : 나는 두 가지 방법을 시도 내가 디버거를 시도했을 때

[TestMethod] 
public void TestMethod1() 
{ 
    var countryCode = "US"; 
    var countryProvider= new CountryProvider(countryCode); 
    var filteredList = new List<string>(); 

    while(countryProvider.Iterator.MoveNext()) 
    { 
     filteredList.Add(countryProvider.Iterator.Current); 
    } 

    Assert.IsTrue(filteredEFIs.Count > 0);   
} 

내가 눈치 그 때마다 호출 MoveNext()로 이동하면 처음부터 계산이 시작되고 Iterator.Current는 항상 null입니다. 그래서 while 루프 Add 전화 모두 상태를 시작하는 (따라서 Currentnull이다) 새로운 반복자 리셋을 얻을 -

+1

당신이 완전한 CountryProvider 클래스를 보여줄 수 : 다른 방법은 내 제공자 유형 부여, (아래 아래) 데코레이터 패턴을 사용하여 내부 열거를 래핑하는 IEnumerator를 장식 패턴을 통해

private IEnumerator<string> m_iterator; public string Iterator { get { if (this.m_iterator == null) { this.ResetIterator(); } return this.m_iterator.MoveNext(); } } public void ResetIterator() { this.m_iterator = this.m_internalIterator(); } private IEnumerator<string> m_internalIterator() { for (int i = 0; i < m_list.Count; i++) { yield return m_list[i]; } yield break; } 

구현합니다입니까? –

+4

예 ... 당신의 질문은 무엇인지 모르겠습니다. 'while'반복마다 새로운 iterator를 만드는 메서드를 호출하면 설명 된대로 정확하게 동작해야합니다. –

+0

열거 자 대신'IEnumerable '을 반환하지 않는 이유는 무엇입니까? 구현이 동일하며 호출자가 훨씬 간단 해지고 작동합니다! –

답변

4

문제는 당신이 새로운 Enumerator 당신의 Iterator 속성이 호출 될 때마다 만드는 것입니다.

올바른 코드는

var iterator = countryProvider.Iterator; 
while(iterator.MoveNext()) 
    { 
     filteredList.Add(iterator.Current); 
    } 

내가 부분적 속성에 상관없이 호출 빈도 "저렴하고 같은"값도 반환하지 않는다 규칙에 의한 생각 될 것이다. 반면에 "GetXXXXX"메서드는 호출간에 변경 될 수있는 무언가를 반환 할 것으로 예상됩니다. 그 패턴을 IEnumerable<T>에서 볼 수 있습니다.이 패턴은 값을 저장하고 사용하도록 권장하는 방법 (GetEnumerator)을 통해 반복기를 제공합니다.

0

인스턴스 문제를 설명해 주셔서 감사합니다. 나는 호출자를 깨뜨리지 않고 프로 바이더 클래스 내의 반복자의 인스턴스를 제어하는 ​​솔루션을 제공했다. 시나리오 나는 호출자가 두 가지를 알고 있다고 가정합니다 - 세션을 시작할 때 다음 항목을 원할 때 여기에서 몇 가지 방법을 원할 때 호출자 내부에서 반복자를 유지 (구현이 조금씩 깨짐)하거나 현재를 깨뜨리지 않는 목적으로 재설정하지 않으면 로컬로 캐시합니다 호출자 구현 (아래에 설명).

private IEnumerator<string> m_iterator; 

public bool MoveNext() 
{ 
    if (this.m_iterator == null) 
    { 
     this.ResetIterator(); 
    } 
    return this.m_iterator.MoveNext();   
} 

public string Current 
{ 
    get 
    { 
     if (this.m_iterator == null) 
     { 
      this.Reset(); 
     } 
     return this.m_iterator.Current; 
    } 
} 

public void Reset() 
{ 
    this.m_iterator = this.m_internalIterator(); 
} 

private IEnumerator<string> m_internalIterator() 
{ 
    for (int i = 0; i < m_list.Count; i++) 
    { 
     yield return m_list[i]; 
    } 
    yield break; 
} 
관련 문제