[C#] ‘IList’대 ‘ICollection’대 ‘Collection’반환

내 공개 API 메서드 및 속성에서 반환해야하는 컬렉션 유형에 대해 혼란스러워합니다.

제가 염두에두고있는 컬렉션은 IList, ICollectionCollection입니다.

이러한 유형 중 하나를 항상 다른 유형보다 선호합니까, 아니면 특정 상황에 따라 달라 집니까?



답변

일반적으로 가능한 한 일반적인 유형, 즉 소비자가 사용해야하는 반환 된 데이터를 충분히 알고있는 유형을 반환해야합니다. 이렇게하면 API를 사용하는 코드를 손상시키지 않고 API 구현을 자유롭게 변경할 수 있습니다.

IEnumerable<T>인터페이스도 반환 유형으로 고려하십시오 . 결과가 반복 될 경우 소비자는 그 이상을 필요로하지 않습니다.


답변

ICollection<T>같은 수집 의미를 노출시키는 인터페이스는 Add(), Remove(), 및 Count.

Collection<T>ICollection<T>인터페이스 의 구체적인 구현입니다 .

IList<T>본질적 ICollection<T>으로 무작위 주문 기반 액세스입니다.

이 경우 결과에 순서 기반 인덱싱 (다음 사용 IList<T>) 과 같은 목록 의미론이 필요한지 여부 또는 정렬되지 않은 결과 “백”을 반환해야하는지 (다음 사용 )를 결정해야합니다 ICollection<T>.


답변

주요 차이점 IList<T>ICollection<T>IList<T>인덱스를 통해 액세스 요소로 할 수 있습니다. IList<T>배열과 유사한 유형을 설명합니다. 의 요소는 ICollection<T>열거를 통해서만 액세스 할 수 있습니다. 둘 다 요소의 삽입 및 삭제를 허용합니다.

컬렉션을 열거하기 만하면되는 IEnumerable<T>경우 선호됩니다. 다른 것보다 두 가지 장점이 있습니다.

  1. 컬렉션에 대한 변경을 허용하지 않습니다 (참조 유형 인 경우 요소에는 변경할 수 없음).

  2. 알고리즘 적으로 생성되고 전혀 컬렉션이 아닌 열거를 포함하여 가능한 가장 다양한 소스를 허용합니다.

Collection<T>주로 컬렉션 구현 자에게 유용한 기본 클래스입니다. 인터페이스 (API)에 노출하면 파생되지 않은 많은 유용한 컬렉션이 제외됩니다.


의 한 가지 단점은 IList<T>배열이이를 구현하지만 항목을 추가하거나 제거 할 수 없다는 것입니다 (즉, 배열 길이를 변경할 수 없음). IList<T>.Add(item)배열 을 호출하면 예외가 발생합니다 . 이를 시도하기 전에 확인할 수 IList<T>있는 부울 속성 IsReadOnly이 있기 때문에 상황은 다소 혼란 스럽습니다 . 하지만 제 눈에는 이것은 여전히 ​​라이브러리의 디자인 결함입니다 . 따라서 List<T>항목을 추가하거나 제거 할 수있는 가능성이 필요할 때 직접 사용 합니다.


답변

IList<T>모든 일반 목록의 기본 인터페이스입니다. 정렬 된 컬렉션이므로 구현시 정렬 된 순서에서 삽입 순서에 이르기까지 순서를 결정할 수 있습니다. 또한 Ilist메서드가 인덱스를 기반으로 목록의 항목을 읽고 편집 할 수 있도록하는 Item 속성이 있습니다. 이를 통해 위치 인덱스의 목록에 값을 삽입하거나 제거 할 수 있습니다.

또한 IList<T> : ICollection<T>에서의 모든 메소드를 ICollection<T>여기에서 구현할 수도 있습니다.

ICollection<T>모든 일반 컬렉션에 대한 기본 인터페이스입니다. 크기, 열거 자 및 동기화 방법을 정의합니다. 컬렉션에 항목을 추가하거나 제거 할 수 있지만 인덱스 속성이 없어서 발생하는 위치는 선택할 수 없습니다.

Collection<T>에 대한 구현을 제공 IList<T>, IList하고 IReadOnlyList<T>.

ICollection<T>대신 보다 좁은 인터페이스 유형을 사용하는 경우 IList<T>변경 사항이 깨지지 않도록 코드를 보호 할 수 있습니다. 와 같이 더 넓은 인터페이스 유형을 사용하면 IList<T>코드 변경이 중단 될 위험이 더 커집니다.

출처 에서 인용 ,

ICollection, ICollection<T>: 컬렉션을 수정하거나 크기에 관심이 있습니다.
IList, IList<T>: 컬렉션을 수정하고 싶고 컬렉션에서 요소의 순서 및 / 또는 위치에 관심이 있습니다.


답변

인터페이스 유형을 반환하는 것이 더 일반적이므로 (특정 사용 사례에 대한 추가 정보가 부족함) 그것에 의지하고 싶습니다. 인덱싱 지원을 노출하려면을 선택하십시오 IList<T>. 그렇지 않으면 ICollection<T>충분합니다. 마지막으로, 반환 된 유형이 읽기 전용임을 나타내려면을 선택합니다 IEnumerable<T>.

이전에 읽지 않은 경우를 대비하여 Brad Abrams와 Krzysztof Cwalina는 “프레임 워크 디자인 지침 : 재사용 가능한 .NET 라이브러리에 대한 규칙, 관용구 및 패턴”이라는 제목의 훌륭한 책을 썼습니다 ( 여기 에서 요약을 다운로드 할 수 있음 ).


답변

이 질문에서 나온 몇 가지 주제가 있습니다.

  • 인터페이스 대 클래스
  • 여러 클래스, 컬렉션, 목록, 배열에서 특정 클래스는 무엇입니까?
  • 공통 클래스 대 하위 항목 ( “제네릭”) 컬렉션

객체 지향 API 임을 강조하고 싶을 수 있습니다.

인터페이스 대 클래스

인터페이스에 대한 경험이 많지 않다면 수업을 고수하는 것이 좋습니다. 필자는 많은 개발자들이 인터페이스로 뛰어 드는 것을 봅니다. 비록 그것이 필요하지 않더라도 말입니다.

그리고 결국에는 좋은 인터페이스 디자인으로 마이그레이션 할 수있는 좋은 클래스 디자인 대신 열악한 인터페이스 디자인을 끝내십시오.

API에서 많은 인터페이스를 볼 수 있지만 필요하지 않다면 서두르지 마십시오.

결국 코드에 인터페이스를 적용하는 방법을 배우게됩니다.

여러 클래스, 컬렉션, 목록, 배열에서 특정 클래스는 무엇입니까?

C # (dotnet)에는 상호 교환 할 수있는 여러 클래스가 있습니다. 이미 언급했듯이 “CanBeSortedClass”와 같은보다 구체적인 클래스의 항목이 필요한 경우 API에서 명시 적으로 지정하십시오.

API 사용자가 클래스를 정렬 할 수 있는지, 아니면 요소에 일부 형식을 적용 할 수 있는지 정말 알아야합니까? 그런 다음 “CanBeSortedClass”또는 “ElementsCanBePaintedClass”를 사용하고, 그렇지 않으면 “GenericBrandClass”를 사용하십시오.

그렇지 않으면 더 일반적인 클래스를 사용하십시오.

공통 컬렉션 클래스 대 하위 항목 ( “제네릭”) 컬렉션

다른 요소를 포함하는 클래스가 있으며 모든 요소가 특정 유형이어야 함을 지정할 수 있습니다.

일반 컬렉션 은 다음과 같이 새 컬렉션을 만들지 않고도 여러 코드 응용 프로그램에 대해 동일한 컬렉션을 사용할 수있는 클래스입니다. 컬렉션 .

API 사용자가 모든 요소에 대해 동일한 매우 구체적인 유형이 필요합니까?

같은 것을 사용하십시오 List<WashingtonApple>.

API 사용자에게 몇 가지 관련 유형이 필요합니까?

노출 List<Fruit>당신의 API를 들어, 및 사용 List<Orange> List<Banana>, List<Strawberry>내부, 어디서 Orange, Banana그리고 Strawberry후손이다 Fruit.

API 사용자에게 일반 유형 컬렉션이 필요합니까?

를 사용하여 List모든 항목은, object(들).

건배.


답변