2013-05-13 4 views
3

나는 다음과 같다 고객에서 몇 가지 코드를 부여했습니다 :사용자 지정 열거자를 정의하거나 기본 제공 열거자를 사용해야합니까?

public class Thing 
{ 
    // custom functionality for Thing... 
} 

public class Things : IEnumerable 
{ 
    Thing[] things; 
    internal int Count { get { return things.Length; } } 

    public Thing this[int i] { get { return this.things[i]; } } 

    public IEnumerator GetEnumerator() { return new ThingEnumerator(this); } 

    // custom functionality for Things... 
} 

public class ThingEnumerator : IEnumerator 
{ 
    int i; 
    readonly int count; 
    Things container; 

    public ThingEnumerator(Things container) 
    { 
     i = -1; 
     count = container.Count; 
     this.container = container; 
    } 

    public object Current { get { return this.container[i]; } } 
    public bool MoveNext() { return ++i < count; } 
    public void Reset() { i = -1; } 
} 

내가 궁금하면이 ThingEnumerator 클래스를 제거 찍었을 위해 더 좋을와 함께 Things.GetEnumerator 전화를 교체 한 것인지 여부입니다 단순히 arrayGetEnumerator에 위임 한 구현입니까? 좋아요 :

public IEnumerator GetEnumerator() { return things.GetEnumerator(); } 

코드를 그대로 유지하면 어떤 장점이 있습니까? (내가 발견 한 또 다른 것은 기존의 코드가 IEnumerator<Thing>으로 IEnumerator를 교체하여 개선 될 수 있다는 것입니다.) 제네릭

+0

직감이 맞습니다. Generics가 C#을 사용하기 전에이 코드는 오래되었습니다. GetEnumerator를 으로 바꿀 수 있습니다. public IEnumerable GoForward() {foreach (var t in things)는 return t를 반환합니다. } 그리고 클래스를 반복하려면 Things things = new Things(); foreach (var t in things) {...} – graumanoz

+0

@graumanoz 생각해 보면, 고객이 오랫동안 두드렸던 코드 일 가능성이 높습니다. 그리고 비슷한 방식으로 쓴다면 더 현대적인 접근 방식을 사용하게 될 것입니다. – TooTone

+0

TooTone 예, 이것은 오래된 코드입니다. 이전에 작성한 작은 방법으로 완전히 대체 할 수 있습니다. – graumanoz

답변

2

일반적으로 고유 한 열거자를 구현해야하는 경우가 있습니다. OnAccess 유형의 이벤트를 어딘가에서 발생시키는 일부 유효성 검사, 로깅, 항목을 잠그고 동시 액세스를 위해 이후에 릴리스하는 일부 논리가있을 수 있습니다 (필자는이를 수행 한 코드를 보았습니다. 마지막 하나, 그것은 이상하다. 그리고 나는 그것을 추천하지 않을 것이다).

당신이 게시 한 예에서 나는 그런 것을 볼 수 없으므로 IEnumerable이 제공하는 것 이상의 어떤 값도 추가하지 않는 것 같습니다. 일반적으로 원하는 것을 수행하는 기본 제공 코드가있는 경우이를 사용하십시오. 자신 만의 롤링으로 달성 할 수있는 것은 유지 관리 할 코드를 더 많이 만드는 것입니다.

3

, IEnumerableIEnumerator 자신을 구현 정말 작은 값이.

이 코드를 제거하면 클래스를 일반적인 컬렉션으로 대체하면 유지 관리 할 코드가 훨씬 적어지고 작동하는 것으로 알려진 코드를 사용하는 이점이 있습니다.

1

사용자 지정 열거 자에서 실제로 사용자 지정 (일종의 유효성 검사와 같은) 작업을 수행하지 않는 한 실제로이 작업을 수행 할 이유가 없습니다.

일반적으로 표준 라이브러리에서 사용 가능한 것으로 이동하십시오. 그들은 더 나은 테스트를 거치고 더 많은 시간을 그들에게 보내고, 코드의 개별 단위로서, 그다음 지출 할 여력이 있으며 왜 바퀴를 재창조해야합니까?

이와 같은 경우에는 코드가 이미 존재하지만 아주 잘 테스트 할 시간이 있으면 코드를 바꾸는 것이 더 나을 수 있습니다. 괜찮은 단위 테스트 커버 리지가 있으면 아무렇지도 않게 느껴질 것입니다.

잠재적 인 불분명 한 버그의 원인을 제거하고 코드를 발견 한 것보다 더 깨끗하게 남겨두면 유지 관리 오버 헤드가 줄어 듭니다. Bob 삼촌은 자랑스러워 할 것입니다.

1

배열 열거자는 사용자 지정 열거 자와 거의 동일하므로 배열의 열거자를 직접 반환 할 수 있습니다.
배열 열거 자도 더 많은 오류 검사를 수행하기 때문에이 작업을 수행하는 것이 좋습니다. 앞에서 설명한 것처럼 간단합니다.

2

.NET generics를 사용할 수있게되기 전에 .NET 1.0/1.1 용으로 작성된 코드와 비슷한 코드가 표시됩니다. 그 당시 자신의 컬렉션 클래스 (일반적으로 System.Collections.CollectionBase에서 파생 됨)를 구현하는 데 가치가 있었기 때문에 indexer 속성은 컬렉션의 런타임 유형에 입력 될 수 있습니다. 그러나 값 유형을 사용하고 boxing/unboxing이 성능 제한이 없다면 CollectionBase에서 상속 받았을 것이므로 GetEnumerator() 또는 Count을 다시 정의 할 필요가 없습니다. 일부 사용자 정의 기능을 위해 사용자 지정 컬렉션이 필요한 경우, 다음 System.Collections.ObjectModel.Collection<Thing>에서 컬렉션을 유도

  1. - 그것은 필요한 모든 후크를 제공

    그러나 지금, 나는이 두 가지 방법 중 하나를 추천 할 것입니다 컬렉션의 항목 삽입, 대체 및 삭제를 제어 할 수 있습니다.

  2. 실제로 열거해야하는 것이 필요한 경우 IList<Thing>List<Thing>으로 백업하여 반환합니다.

관련 문제