2011-02-11 3 views
37

IEnumerableIEnumerable<T>의 차이점은 무엇입니까?IEnumerable과 IEnumerable의 차이점 <T>?

이 두 인터페이스를 모두 구현 한 많은 프레임 워크 클래스를 보았으므로이 두 인터페이스를 구현하면 어떤 이점이 있는지 알고 싶습니다.

가 정의 된 한 방법을 찾아 보게하십시오 : 우리가 보듯이

public interface IEnumerable 
{ 
    [DispId(-4)] 
    IEnumerator GetEnumerator(); 
} 
public interface IEnumerable<T> : IEnumerable 
{ 
    IEnumerator<T> GetEnumerator(); 
} 

, IEnumerable<T>은 왜 우리가 대신 IEnumerable<T> 모두 구현합니까, 즉 IEnumerableIEnumerable<T> 상속을 가지고 어떤 의미 IEnumerable에서 파생를 ? IEnumerable<T>을 구현하는 것만으로 충분하지 않습니까?

  • IListIList<T>
  • ICollectionICollection<T>

나뿐만 아니라 이들에 대해 알고 싶습니다 :

은 마찬가지로, 다른 유사한 쌍있다.

답변

48

기본적으로 비동기 인터페이스가 .NET 1.0 및 1.1에서 처음 등장했습니다. 그런 다음 .NET 2.0이 나왔을 때, 이에 상응하는 항목이 나왔습니다. 당신은 모두를 구현하는이 기본적으로, 당신은 명시 적 인터페이스를 사용해야합니다 - 제네릭 구현의 관점에서 .NET 1.0 :

로 만들었 더라면 생명 "은"IEnumerable<T> 대신 모두의 많은 간단했을 것이다 두 가지 모두 파라미터가없는 GetEnumerator 메서드를 정의한다는 점을 감안할 때 구현도 마찬가지입니다. 한편

public IEnumerator<T> GetEnumerator() 
{ 
    // Return real iterator 
} 

// Explicit implementation of nongeneric interface 
IEnumerator IEnumerable.GetEnumerator() 
{ 
    // Delegate to the generic implementation 
    return GetEnumerator(); 
} 

, 당신은 거의 다행히 손으로 완전히이 일을 구현할 필요가 없습니다 (yield return 등으로) C# 2에 도입 된 반복기 블록 : IEnumerator<T>이 너무 IEnumerator를 확장, 그것은 일반적으로이 같은입니다. 위와 같은 내용을 작성한 다음 GetEnumerator 메서드에서 yield return을 사용해야 할 수 있습니다. 하지ICollection을 확장

IList<T>하지IList을 확장한다는 것을

주 및 ICollection<T>는 않습니다. 그 이유는 형식 안전성이 떨어지기 때문입니다. 일반적인 반복기는 임의의 값을 object으로 변환 (비공식 반복기)하기 때문에 비 반복 반복자로 볼 수 있습니다. IListICollection은 값을 에 추가하면이됩니다. 수집; 문자열을 IList<int>에 추가 (말하기)하는 것은 의미가 없습니다.

편집 : 우리가 IEnumerable<T>을 필요로하는 이유는 유형 안전 방식으로 반복하고 그 정보를 전파 할 수 있기 때문입니다. IEnumerable<string>을 반환하면 문자열 참조 또는 null이 반환되는 모든 정보를 안전하게 가정 할 수 있습니다. IEnumerable을 사용하면 Current 속성이 IEnumerator 일 때 object 일 뿐이므로 시퀀스에서 반환 된 각 요소를 효과적으로 캐스팅 (foreach 문에 암시 적으로 포함)해야했습니다.왜 우리는 여전히IEnumerable이 필요합니다 - 왜냐하면 오래된 인터페이스는 절대로 사라지지 않기 때문입니다. 이 코드를 사용하는 코드가 너무 많습니다.

그것은 IEnumerable을 연장하지 IEnumerable<T> 가능했을 것이다, 그러나 다음 IEnumerable<T>을 활용하고자하는 코드는 IEnumerable를 받아들이는 방법으로 호출 할 수 - 및 .NET 1.1에서 그런 방법이 많이 있었다 및 1.0.

+12

제네릭이 .NET 1.0으로 만들었다면 수명이 훨씬 더 간단했을 것입니다 ... – Oded

+0

@ 존 : 질문 : 왜 우리는 이미 IEnumerable 을 구현할 때'IEnumerable'을 구현해야합니까? , 혹은 그 반대로도? – Nawaz

+0

@Nawaz : 내 대답을 편집했습니다. 제네릭이 좋은 이유에 대해 얼마나 편안합니까? –

5

하나는 Object 유형의 객체, 다른 반환

2

당신이 클래스가 충분히 IEnumerable을 < T, 그 필요하지만하지 좋은 IEnumerable을입니다 구현합니다>하지만, 모두 정의를 참조 왜 T 형식의 개체를 반환 때때로 하위 인터페이스를 나열하는 자체 문서화 작업을 수행합니다. 고려하십시오.

interface IA { } 
interface IB : IA { } 

class A : IB {} // legal, IB implements IA 

class B : IA, IB {} // also legal, possible more clear on intent 
1

반복을 통해 IEnumerator가 상태를 유지하는 동안. 커서 위치를 기억하고 IEnumerable은 커서 위치를 기억하지 않습니다.